ExecutorService線程池
ExecutorService建立多線程的步驟:1。定義線程類 | class Handler implements Runnable{ } |
2。建立ExecutorService線程池 | ExecutorService executorService =Executors.newCachedThreadPool(); 或者 int cpuNums = Runtime.getRuntime().availableProcessors(); //獲取當前係統的CPU 數目 ExecutorService executorService=Executors.newFixedThreadPool(cpuNums * POOL_SIZE); //ExecutorService通常根據係統資源情況靈活定義線程池大小 |
3。調用線程池操作 | 循環操作,成為daemon,把新實例放入Executor池中 while(true){ executorService.execute(newHandler(socket)); // class Handler implements Runnable{ 或者 executorService.execute(createTask(i)); //private static Runnable createTask(final int taskID) } execute(Runnable對象)方法 其實就是對Runnable對象調用start()方法 (當然還有一些其他後台動作,比如隊列,優先級,IDLE timeout,active激活等) |
幾種不同的ExecutorService線程池對象
1.newCachedThreadPool() | -緩存型池子,先查看池中有沒有以前建立的線程,如果有,就reuse.如果沒有,就建一個新的線程加入池中 -緩存型池子通常用於執行一些生存期很短的異步型任務 因此在一些麵向連接的daemon型SERVER中用得不多。 -能reuse的線程,必須是timeout IDLE內的池中線程,缺省timeout是60s,超過這個IDLE時長,線程實例將被終止及移出池。 注意,放入CachedThreadPool的線程不必擔心其結束,超過TIMEOUT不活動,其會自動被終止。 |
2. newFixedThreadPool | -newFixedThreadPool與cacheThreadPool差不多,也是能reuse就用,但不能隨時建新的線程 -其獨特之處:任意時間點,最多隻能有固定數目的活動線程存在,此時如果有新的線程要建立,隻能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子 -和cacheThreadPool不同,FixedThreadPool沒有IDLE機製(可能也有,但既然文檔沒提,肯定非常長,類似依賴上層的TCP或UDPIDLE機製之類的),所以FixedThreadPool多數針對一些很穩定很固定的正規並發線程,多用於服務器 -從方法的源代碼看,cache池和fixed池調用的是同一個底層池,隻不過參數不同: fixed池線程數固定,並且是0秒IDLE(無IDLE) cache池線程數支持0-Integer.MAX_VALUE(顯然完全沒考慮主機的資源承受能力),60秒IDLE |
3.ScheduledThreadPool | -調度型線程池 -這個池子裏的線程可以按schedule依次delay執行,或周期執行 |
4.SingleThreadExecutor | -單例線程,任意時間池中隻能有一個線程 -用的是和cache池和fixed池相同的底層池,但線程數目是1-1,0秒IDLE(無IDLE) |
上麵四種線程池,都使用Executor的缺省線程工廠建立線程,也可單獨定義自己的線程工廠
下麵是缺省線程工廠代碼:
staticclass DefaultThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1); final ThreadGroup group; final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null)? s.getThreadGroup():Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() +"-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r,namePrefix +threadNumber.getAndIncrement(),0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } |
public static ExecutorServicenewCachedThreadPool(ThreadFactorythreadFactory) { |
Executor的execute()方法
execute() 方法將Runnable實例加入pool中,並進行一些pool size計算和優先級處理
execute() 方法本身在Executor接口中定義,有多個實現類都定義了不同的execute()方法
如ThreadPoolExecutor類(cache,fiexed,single三種池子都是調用它)的execute方法如下:
publicvoid execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize ||!addIfUnderCorePoolSize(command)) { if (runState == RUNNING &&workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } } |
最後更新:2017-04-04 07:03:18
上一篇:
linux簡單之美(二)
下一篇:
iOS 開發,工程中混合使用 ARC 和非ARC
你了解多少考研數學高分複習方法?
Only the original thread that created a view hierarchy can touch its views——Handler的使用
對話黃誌敏|探索數據領域的新可能 文科生如何做編程和統計?
Alibaba Single's Day Festival – An Evolution of Alibaba Cloud's Underlying Infrastructure
獨家:阿裏巴巴DevOps落地實踐玩法及思路解析
InstantRun原理(1)——初始化邏輯
一位缺覺的父親記錄了他雙胞胎寶寶的睡眠數據 並交給機器學習,結果……
EDAS快速入門指南 - 部署第一個應用
物聯網技術在物流行業的應用
自旋鎖