ExecutorService 創建多線程的步驟:php
1。定義線程類 | class Handler implements Runnable{ } |
2。創建ExecutorService線程池 | ExecutorService executorService = Executors.newCachedThreadPool(); 或者web int cpuNums = Runtime.getRuntime().availableProcessors(); |
3。調用線程池操做 | 循環操做,成爲daemon,把新實例放入Executor池中 while(true){ executorService.execute(new Handler(socket)); // class Handler implements Runnable{ 或者 executorService.execute(createTask(i)); //private static Runnable createTask(final int taskID) } execute(Runnable對象)方法 |
幾種不一樣的ExecutorService線程池對象多線程
1.newCachedThreadPool() | -緩存型池子,先查看池中有沒有之前創建的線程,若是有,就reuse.若是沒有,就建一個新的線程加入池中 -緩存型池子一般用於執行一些生存期很短的異步型任務 所以在一些面向鏈接的daemon型SERVER中用得很少。 -能reuse的線程,必須是timeout IDLE內的池中線程,缺省timeout是60s,超過這個IDLE時長,線程實例將被終止及移出池。 注意,放入CachedThreadPool的線程沒必要擔憂其結束,超過TIMEOUT不活動,其會自動被終止。 |
2. newFixedThreadPool | -newFixedThreadPool與cacheThreadPool差很少,也是能reuse就用,但不能隨時建新的線程 -其獨特之處:任意時間點,最多隻能有固定數目的活動線程存在,此時若是有新的線程要創建,只能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子 -和cacheThreadPool不一樣,FixedThreadPool沒有IDLE機制(可能也有,但既然文檔沒提,確定很是長,相似依賴上層的TCP或UDP IDLE機制之類的),因此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的缺省線程工廠創建線程,也可單獨定義本身的線程工廠
下面是缺省線程工廠代碼:併發
static class DefaultThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1); final ThreadGroup group; final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; DefaultThreadFactory() { public Thread newThread(Runnable r) { |
也可本身定義ThreadFactory,加入創建池的參數中socket
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { |
Executor的execute()方法
execute() 方法將Runnable實例加入pool中,並進行一些pool size計算和優先級處理
execute() 方法自己在Executor接口中定義,有多個實現類都定義了不一樣的execute()方法
如ThreadPoolExecutor類(cache,fiexed,single三種池子都是調用它)的execute方法以下:ui
public void 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 } } |