大家都說Java有三種創(chuàng)建線程的方式!
在Java中,創(chuàng)建線程是一項非常重要的任務。線程是一種輕量級的子進程,可以并行執(zhí)行,使得程序的執(zhí)行效率得到提高。Java提供了多種方式來創(chuàng)建線程,但許多人都認為Java有三種創(chuàng)建線程的方式,它們分別是繼承Thread類、實現(xiàn)Runnable接口和使用線程池。
但是,你們知道嗎?其實在創(chuàng)建線程的過程中,除了上述描述的方法還有很多種方式可以選擇哦。今天,我們就來揭開這個驚天秘密,一起來了解一下Java并發(fā)編程中創(chuàng)建線程的八股文。
一. 創(chuàng)建線程的方法:
1. 繼承Thread類創(chuàng)建線程
這是最基本的創(chuàng)建線程的方式,我們可以通過繼承Thread類來創(chuàng)建一個自定義的線程類,然后重寫run()方法,實現(xiàn)線程的邏輯。
public class MyThread extends Thread { ? ?
? ?public void run() { ? ? ? ?// 線程邏輯
? ?}
}// 創(chuàng)建并啟動線程MyThread myThread = new MyThread();
myThread.start();
2. 實現(xiàn)Runnable接口創(chuàng)建線程
這是另一種常見的創(chuàng)建線程的方式,我們可以通過實現(xiàn)Runnable接口來創(chuàng)建一個自定義的線程類,然后將該類實例化并傳遞給Thread類的構造方法中,最后調(diào)用start()方法啟動線程。
public class MyRunnable implements Runnable {public void run() {// 線程邏輯}
}// 創(chuàng)建并啟動線程MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);
thread.start();
3. 實現(xiàn)Callable接口創(chuàng)建線程
Callable接口與Runnable接口類似,但是它可以返回一個結果并拋出異常。我們可以通過實現(xiàn)Callable接口來創(chuàng)建一個自定義的線程類,然后將該類實例化并傳遞給FutureTask類的構造方法中,最后調(diào)用start()方法啟動線程。
public class MyCallable implements Callable {public String call() throws Exception {// 線程邏輯return "result";
}
}// 創(chuàng)建并啟動線程MyCallable myCallable = new MyCallable();FutureTask futureTask = new FutureTask<>(myCallable);Thread thread = new Thread(futureTask);
thread.start();// 獲取線程返回結果String result = futureTask.get();
4. 使用線程池創(chuàng)建線程
線程池是一種重用線程的機制,可以減少線程創(chuàng)建和銷毀的開銷。我們可以通過Executors類提供的靜態(tài)方法來創(chuàng)建不同類型的線程池,然后將任務提交給線程池執(zhí)行。
ExecutorService executorService = Executors.newFixedThreadPool(10);// 提交任務并執(zhí)行executorService.submit(new Runnable() {public void run() {// 線程邏輯}
});// 關閉線程池executorService.shutdown();
5. 使用定時器創(chuàng)建線程
定時器可以用來定時執(zhí)行某個任務。我們可以通過Timer類來創(chuàng)建一個定時器,然后將任務添加到定時器中執(zhí)行。

6. 使用ScheduledExecutorService創(chuàng)建線程
ScheduledExecutorService
是一種可以調(diào)度任務執(zhí)行的線程池。我們可以通過它來創(chuàng)建一個定時任務,也可以創(chuàng)建一個周期性任務。
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);// 創(chuàng)建定時任務并執(zhí)行scheduledExecutorService.schedule(new Runnable() { ? ?
? ?public void run() { ? ? ? ?// 線程邏輯
? ?}
}, 1, TimeUnit.SECONDS);// 創(chuàng)建周期性任務并執(zhí)行scheduledExecutorService.scheduleAtFixedRate(new Runnable() { ? ?
? ?public void run() { ? ? ? ?// 線程邏輯
? ?}
}, 1, 1, TimeUnit.SECONDS);// 關閉線程池scheduledExecutorService.shutdown();
7. 使用Fork/Join框架創(chuàng)建線程
Fork/Join框架是Java 7中引入的一種并行執(zhí)行任務的機制。它可以將一個大任務拆分成多個小任務并行執(zhí)行,最后將結果合并。
public class MyTask extends RecursiveTask { ? ?private int start; ? ?private int end; ? ?public MyTask(int start, int end) { ? ? ? ?this.start = start; ? ? ? ?this.end = end;
? ?} ? ?
? ?protected Integer compute() { ? ? ? ?if (end - start <= 1000) { ? ? ? ? ? ?// 執(zhí)行小任務
? ? ? ? ? ?return 0;
? ? ? ?} else { ? ? ? ? ? ?// 拆分大任務
? ? ? ? ? ?int mid = (start + end) / 2; ? ? ? ? ? ?MyTask leftTask = new MyTask(start, mid); ? ? ? ? ? ?MyTask rightTask = new MyTask(mid + 1, end);
? ? ? ? ? ?leftTask.fork();
? ? ? ? ? ?rightTask.fork(); ? ? ? ? ? ?// 合并結果
? ? ? ? ? ?return leftTask.join() + rightTask.join();
? ? ? ?}
? ?}
}// 創(chuàng)建并執(zhí)行任務ForkJoinPool forkJoinPool = new ForkJoinPool();MyTask myTask = new MyTask(1, 10000);int result = forkJoinPool.invoke(myTask);
8. 使用Semaphore創(chuàng)建線程
Semaphore是一種計數(shù)器,用來控制同時訪問某個資源的線程數(shù)量。我們可以通過Semaphore來創(chuàng)建一個有限的線程池。
Semaphore semaphore = new Semaphore(10);// 創(chuàng)建并執(zhí)行任務Runnable runnable = new Runnable() { ? ?
? ?public void run() { ? ? ? ?try {
? ? ? ? ? ?semaphore.acquire(); ? ? ? ? ? ?// 線程邏輯
? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ?e.printStackTrace();
? ? ? ?} finally {
? ? ? ? ? ?semaphore.release();
? ? ? ?}
? ?}
};for (int i = 0; i < 100; i++) { ? ?new Thread(runnable).start();
}
二. 線程和線程體的關系
說到線程大家都知道,它是一種重要的多任務處理機制??梢宰屛覀兺瑫r執(zhí)行多個任務,并且可以提高程序的效率。?上述也給大家?guī)砹撕芏喾N創(chuàng)建線程的方式,但是說到這里,我發(fā)現(xiàn)經(jīng)常有朋友問:線程體和線程是什么關系?其實,簡單說:線程體就是是線程的具體執(zhí)行代碼。那么接下來就讓我們具體來看看線程和線程體的關系吧!
1. 線程和線程體的關系
在Java中,線程和線程體是兩個不同的概念。
線程是一條執(zhí)行路徑,線程體是線程的具體執(zhí)行代碼。?每個線程都有一個與之相關的線程體。線程體是實現(xiàn)了Runnable接口的類的實例。線程體可以是一個獨立的類,也可以是一個內(nèi)部類。線程創(chuàng)建之后,它的run()方法就會被調(diào)用,run()方法中的代碼就是線程體的執(zhí)行代碼。
2. 案例說明
可能會有朋友覺得上述的解釋過于書面化,那么如果通過生活實例來說明線程體和線程的關系的話,我們可以將線程理解成為一個人,線程體則是這個人所做的事情。
比如,在上班的路上,我們可以同時進行多個任務,比如聽音樂、看書、發(fā)短信等等。這些任務就可以看做是這個人的線程體。線程就是這個人同時進行多個任務的機制。如果我們只有一個人,那么這個人必須先做完一個任務才能開始做下一個任務。這樣就會浪費很多時間。但是如果我們有兩個人,那么一個人可以看書,另一個人可以聽音樂,這樣就可以同時進行多個任務,提高了效率。
3. 代碼案例
下面給大家?guī)硪粋€:創(chuàng)建多個線程來同時執(zhí)行多個任務的簡單的代碼案例,示例如下:
public class MyThread implements Runnable { ? ?private String taskName; ? ?public MyThread(String taskName) { ? ? ? ?this.taskName = taskName;
? ?} ? ?
? ?public void run() { ? ? ? ?for (int i = 0; i < 5; i++) {
? ? ? ? ? ?System.out.println(taskName + "執(zhí)行了第" + (i + 1) + "次任務"); ? ? ? ? ? ?try {
? ? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ?}
? ? ? ?}
? ?} ? ?public static void main(String[] args) { ? ? ? ?MyThread thread1 = new MyThread("線程1"); ? ? ? ?MyThread thread2 = new MyThread("線程2"); ? ? ? ?Thread t1 = new Thread(thread1); ? ? ? ?Thread t2 = new Thread(thread2);
? ? ? ?t1.start();
? ? ? ?t2.start();
? ?}
}
在這個案例中,我們創(chuàng)建了兩個線程,分別執(zhí)行不同的任務。每個線程的線程體是MyThread類的run()方法。在run()方法中,每個線程會執(zhí)行5次任務,并在每次任務之間暫停1秒鐘。通過創(chuàng)建多個線程,我們可以同時執(zhí)行多個任務,提高程序的效率。
4. 小結
通過上述介紹的Java線程和線程體的關系,大家應該都清楚了。線程是一種多任務處理機制,線程體是線程的具體執(zhí)行代碼。在Java中,我們可以通過創(chuàng)建多個線程來同時執(zhí)行多個任務,提高程序的效率。希望上述可以幫助大家更好地理解Java中線程和線程體的概念哦。