本文參考自:http://blog.csdn.net/zcc_0015/article/details/15502813
一、活動對象定義:
活動對象工作在對象級別而不像其他設計模式工作在對象繼承層級關係中。它將方法的調用和其實際的執行解耦,方法的執行位於對象本身的控制線程中,因而也不會阻塞調用者。總的說來,活動對象模式有6個元素:
1.代理。以公共方法的方式向客戶對象提供訪問接口。
2.接口。定義了活動對象上的方法請求。
3.隊列。保存來自客戶的掛起的請求。
4.調度器。決定從掛起的隊列中選取哪個請求來執行。
5.實現。活動對象方法的實現。
6.回調/變量。客戶對象用它來獲取請求執行的結果,活動方法的執行結果通常被封裝到成爲future的對象中。該future對象中包含了一個類似於佔位符的東西。一旦活動對象完成了方法執行就會將結果放到future的佔位符上。但在方法完成之前嘗試獲取佔位符上的內容將會阻塞線程。
二、活動對象的特徵:
基於消息機制:對活動對象的請求和可能的參數都被轉化爲消息,這些消息被轉發給活動對象實際實現並排隊等待處理。處理結果以future對象返還給提出請求的對象。
異步調用:對活動對象的請求被異步執行,實際由活動對象的工作線程處理請求,故不會阻塞調用者。僅當請求未完成執行時,調用者試圖獲取處理結果時會被阻塞。
線程安全:活動對象天生是線程安全的。因爲他順序地從請求隊列摘取消息進行處理,並且始終在一個單獨的線程中執行,由於不存在資源競爭,所以也不用擔心同步、死鎖等問題。同步仍舊會發生,但它通過將方法調用排隊,使得任何時刻都只能發生一個調用,從而將同步控制在消息的級別上發生。
三、活動對象的應用場景:
適合於實時跟蹤具有按某一特定順序執行而又互不影響的多線程任務其執行狀況的情景
四、活動對象的實例:
import java.util.*;
import java.util.concurrent.*;
public class ActiveObjectsDemo {
//創建ActiveObjectDemo對象的工作線程,Executors.newSingleThreadExecutor()創建的是單個線程
//所有在ex中執行的方法都在這個線程中串行地逐個執行
private ExecutorService ex=
Executors.newSingleThreadExecutor();
private Random rand=new Random(47);
private void pause(int factor){
try{
TimeUnit.MICROSECONDS.sleep(100+rand.nextInt(factor));
}catch(InterruptedException e){
System.out.println("sleep() interrupted");
}
}
public Future<Integer> calculateInt(final int x ,final int y){
/*
* ExecutorService的submit方法啓動的線程會返回一個Future對象
* 當方法執行完畢會將結果保存到該Future對象中。
*/
return ex.submit(new Callable<Integer>() {
public Integer call(){
System.out.println("starting "+x+"+"+y);
pause(2000);
return x+y;
}
});
}
public Future<Float> calculateFloat(final float x ,final float y){
/*
* ExecutorService的submit方法啓動的線程會返回一個Future對象
* 當方法執行完畢會將結果保存到該Future對象中。
*/
return ex.submit(new Callable<Float>() {
public Float call(){
System.out.println("starting "+x+"+"+y);
pause(2000);
return x+y;
}
});
}
public void shutdown() {
ex.shutdown();
}
public static void main(String[] args) {
ActiveObjectsDemo demo=new ActiveObjectsDemo();
//使用CopyOnWriteArrayList可以防止併發修改異常(ConcurrentModificationException)
List<Future<?>> results=new CopyOnWriteArrayList<Future<?>>();
/*
* 所有對calculateFloat和calculateInt讀調用都是立即返回
* 並且就算是“同時”調用這些方法,它們也會排隊串行執行,避免了顯示地同步需求
*/
for(float f=0.0f;f<1.0f;f+=0.2f)
results.add(demo.calculateFloat(f, f));
for(int i=0;i<5;i++)
results.add(demo.calculateInt(i, i));
System.out.println("All asynch calls made");
while(results.size()>0){
for(Future<?> f: results){
try{
//阻塞並獲取調用結果
System.out.println(f.get());
}catch(Exception exception){
throw new RuntimeException(exception);
}
results.remove(f);
}
}
demo.shutdown();
}
}