從java5開始,java就提供了名叫Executor framework的機制,主要是圍繞着Executor接口, 它的接口 ExecutorService, 以及實現了這兩個接口的ThreadPoolExecutor類來展開,這種機制把線程的執行和創建分離開了,你只需要創建一個線程,然後把線程丟給Executor,讓它執行去吧。使用這個機制的另外一個好處是可以使用Callable接口,它類似於Runnable接口,但是有兩個不一樣的特性。
- 它的主要方法是call(), 它可以攜帶一個返回值。
- 當你發送了一個Callable對象給executor之後,你可以拿到一個實現了Future接口的對象,通過這個對象,你可以控制對象的狀態以及Callable對象的結果。
package threadPool.executorDemo;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
*
* 類似於Runnable接口,具有以下特點
* 1 它的主要方法是call(), 它可以攜帶一個返回值。
* 2 當你發送了一個Callable對象給executor之後,
* 你可以拿到一個實現了Future接口的對象,通過這個對象,你可以控制對象的狀態以及Callable對象的結果。
*
* 3 Callable 接口類似於 Runnable,兩者都是爲那些其實例可能被另一個線程執行的類設計的。
* 但是 Runnable 不會返回結果,並且無法拋出經過檢查的異常。
* @version [版本號, 2014-3-10]
* @see [相關類/方法]
* @since [產品/模塊版本]
*/
public class FactorialCalculator implements Callable<Integer> {
private Integer number;
public FactorialCalculator(Integer number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int result = 1;
if ((number == 0) || (number == 1)) {
result = 1;
}
else {
for (int i = 2; i <= number; i++) {
result *= i;
TimeUnit.MILLISECONDS.sleep(50L);
}
}
System.out.printf("%s: %d\n", Thread.currentThread().getName(), result);
return result;
}
}
package threadPool.executorDemo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class TestDemo3 {
/**
* 數的階乘 n!
* <功能詳細描述>
* @param args
* @see [類、類#方法、類#成員]
*/
public static void main(String[] args) {
//創建了兩條線程
ThreadPoolExecutor pool = (ThreadPoolExecutor)Executors.newFixedThreadPool(2);
//添加線程池關閉後出現的異常處理
pool.setRejectedExecutionHandler(new RejectedTaskController());
//用於存放Future接口的對象容器
List<Future<Integer>> resultList = new ArrayList<Future<Integer>>();
FactorialCalculator calculator = new FactorialCalculator(6 );
//提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future
//Future接口 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果
Future<Integer> result = pool.submit(calculator);
resultList.add(result);
FactorialCalculator calculator1 = new FactorialCalculator(5);
Future<Integer> result1 = pool.submit(calculator1);
resultList.add(result1);
for (int i = 0; i < resultList.size(); i++) {
result = resultList.get(i);
Integer number = null;
try {
//如有必要,等待計算完成,然後獲取其結果
number = result.get();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
System.out.printf("Main: Task %d: %d\n", i, number);
}
//關閉線程池
//按過去執行已提交任務的順序發起一個有序的關閉,但是不接受新任務
pool.shutdown();
}
}
package threadPool.executorDemo;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
/**
*
* 當線程池關閉後,用來處理線程異常
* <功能詳細描述>
*
* @version [版本號, 2014-3-10]
* @see [相關類/方法]
* @since [產品/模塊版本]
*/
public class RejectedTaskController implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//打印線程信息
System.out.printf("RejectedTaskController: The task %s has been rejected\n", r.toString());
//打印線程池信息
System.out.printf("RejectedTaskController: %s\n", executor.toString());
//如果此執行程序處於在 shutdown 或 shutdownNow 之後正在終止但尚未完全終止的過程中,則返回 true
System.out.printf("RejectedTaskController: Terminating: %s\n", executor.isTerminating());
//如果關閉後所有任務都已完成,則返回 true
System.out.printf("RejectedTaksController: Terminated: %s\n", executor.isTerminated());
}
}