基本的執行緒機制(二)
2.Thread類
將Runnable物件轉變為工作任務的傳統方式是把他提交給一個Thread構造器,如下
public class BasicThreads {
public static void main(String[] args) {
Thread thread=new Thread(new Liftoff());
thread.start();
System.out.println("waiting ofr LiftOff");
}
}/* out
waiting ofr LiftOff
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2),
#0(1), #0(Liftoff!),
*/
詳細分析這段程式碼
Thread構造器只需要一個Runnable物件。Thread物件的start()方法為該執行緒執行必需的初始化操作,然後呼叫Runnable的run()方法,這時可以看見main方法的waiting Liftoff也執行,因為LiftOff.run中的方法和main是不同執行緒執行,接下來我們來新增更多的執行緒驅動
public class MoreBasicThread {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread(new Liftoff()).start();
}
System.out.println("waiting for LiftOff");
}
}/*out
waiting for LiftOff
#4(9), #1(9), #2(9), #0(9), #2(8), #1(8), #3(9), #4(8), #3(8), #1(7), #2(7), #0(8), #2(6), #1(6), #3(7), #4(7), #3(6), #1(5), #2(5), #0(7), #2(4), #1(4), #3(5), #4(6), #3(4), #1(3), #2(3), #0(6), #2(2), #1(2), #3(3), #4(5), #3(2), #1(1), #2(1), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #2(Liftoff!), #1(Liftoff!), #3(1), #4(4), #3(Liftoff!), #4(3), #4(2), #4(1), #4(Liftoff!),
*/
對於程式碼中我們添加了一個for迴圈啟動了5個執行緒,對於輸出中我們可以看見不同人物的執行的執行緒被換進換出時混在一起。這種交換是由執行緒排程器自動控制的,如果在你的處理器上有多個處理器,執行緒排程器將會在這些處理器之間默默地分發執行緒。
這個結果的輸出每次並不是相同,執行緒的排程機制是非確定性的。
3.EXecutor
think in java中說Executor在java SE5/6中是啟動任務的優選方法。
在這裡我查詢了一下相關資料在7和8裡面也是優選的方法
public interface Executor {
void execute(Runnable command);
}
上面是這個介面的定義。
我們可以在第二節裡面顯示建立Thread物件代替。
thin in java沒有講其好處寫得詳盡,讓我開始覺得並沒有好大的作用,這裡詳細分析這個好處。
- 第一個好處也是think in java書上提到的將客戶端和任務執行分開,這點就是命令模式,將任務的提交過程和執行過程解耦
- 第二個好處也是最重要的好處:我們使用Thread中建立大量執行緒時,會把執行緒建立語句隨意地散落在程式碼中,無法統一管理執行緒的數量,而過量的執行緒建立將直接使系統崩潰,他和Executor不同Executor從執行緒池中提取執行緒,通過重用現有的執行緒而不是一味的建立新縣城。可以在處理多個請求時分攤線上程建立和銷燬過程中產生巨大的開銷。
現在討論Executor的使用
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService executorService=Executors.newCachedThreadPool();
for(int i=0;i<5;i++){
executorService.execute(new Liftoff());
}
executorService.shutdown();
}
}/*Out
#0(9), #4(9), #2(9), #1(9), #3(9), #1(8), #2(8), #3(8), #4(8), #4(7), #1(7), #0(8), #1(6), #4(6), #3(7), #2(7), #3(6), #4(5), #1(5), #0(7), #3(5), #4(4), #3(4), #4(3), #2(6), #4(2), #3(3), #4(1), #1(4), #4(Liftoff!), #0(6), #0(5), #1(3), #3(2), #2(5), #3(1), #1(2), #1(1), #1(Liftoff!), #0(4), #3(Liftoff!), #2(4), #0(3), #2(3), #0(2), #2(2), #0(1), #2(1), #0(Liftoff!), #2(Liftoff!), */
這裡我們使用ExecutorService(具有生命週期的Executor:執行,關閉,終止)ExecutorService在初始化建立時處於執行狀態。shutdown方法將執行平緩的關閉過程:不在接受新任務,同事等待已經提交的任務執行完成(包括哪些還未開始執行的任務)。shutdownNow方法將執行粗暴的關閉過程:將把所有的任務(不管你在執行還是沒有執行)全部取消。
這裡對newCachedThreadPool進行分析:
除了newCachedThreadPool之外還有FixedThreadPool和SingleThreadExecutor進行分析。
newCachedThreadPool:newCachedThreadPool將建立一個可快取的執行緒池,如果執行緒池的當前規模超過了處理需求,那麼將回收空閒執行緒;而當需求增加時,可以新增新的執行緒,執行緒池的規模不存在任何限制。
newFixedThreadPool:newFixedThreadPool將建立一個固定大小的執行緒池,每當提交一個任務就建立一個執行緒,直到達到執行緒池的最大數量,這時執行緒池的規模將不再變化;
newSingleThreadExecutor:newSingleThreadExecutor是一個單執行緒的Executor,它建立單個工作者執行緒執行任務,如果這個執行緒異常結束,會建立另一個執行緒代替。