import java.util.List;
import java.util.concurrent.*;
publicclass CallableDemo {
publicstaticvoid main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
//創建10個任務並執行
for (int i = 0; i < 10; i++) {
//使用ExecutorService執行Callable類型的任務,並將結果保存在future變量中
Future<String> future = executorService.submit(new TaskWithResult(i));
//將任務執行結果存儲到List中
resultList.add(future);
}
//遍歷任務的結果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); //打印各個線程(任務)執行的結果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
//啓動一次順序關閉,執行以前提交的任務,但不接受新任務。如果已經關閉,則調用沒有其他作用。
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable<String> {
privateint id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() throws Exception {
System.out.println("call()方法被自動調用,幹活!!! " + Thread.currentThread().getName());
//一個模擬耗時的操作
for (int i = 999999; i > 0; i--) ;
return"call()方法被自動調用,任務的結果是:" + id + " " + Thread.currentThread().getName();
}
}
call()方法被自動調用,幹活!!! pool-1-thread-3
call()方法被自動調用,幹活!!! pool-1-thread-4
call()方法被自動調用,幹活!!! pool-1-thread-6
call()方法被自動調用,幹活!!! pool-1-thread-2
call()方法被自動調用,幹活!!! pool-1-thread-5
call()方法被自動調用,任務的結果是:0 pool-1-thread-1
call()方法被自動調用,任務的結果是:1 pool-1-thread-2
call()方法被自動調用,幹活!!! pool-1-thread-2
call()方法被自動調用,幹活!!! pool-1-thread-6
call()方法被自動調用,幹活!!! pool-1-thread-4
call()方法被自動調用,任務的結果是:2 pool-1-thread-3
call()方法被自動調用,幹活!!! pool-1-thread-3
call()方法被自動調用,任務的結果是:3 pool-1-thread-4
call()方法被自動調用,任務的結果是:4 pool-1-thread-5
call()方法被自動調用,任務的結果是:5 pool-1-thread-6
call()方法被自動調用,任務的結果是:6 pool-1-thread-2
call()方法被自動調用,任務的結果是:7 pool-1-thread-6
call()方法被自動調用,任務的結果是:8 pool-1-thread-4
call()方法被自動調用,任務的結果是:9 pool-1-thread-3
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) |
下面是缺省線程工廠代碼:
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() { 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 ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { |
Executor的execute()方法
execute() 方法將Runnable實例加入pool中,並進行一些pool size計算和優先級處理
execute() 方法本身在Executor接口中定義,有多個實現類都定義了不同的execute()方法
如ThreadPoolExecutor類(cache,fiexed,single三種池子都是調用它)的execute方法如下:
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 } } |