java 线程 设计模式_Java多线程设计模式(四)
Future Pattern
在Thread-Per-Message Pattern中,我們研究過“收到每個請求建立一個線程”的做法,但這樣的請求是不要求有返回值的。如果當需要返回值,但由于后臺處理需要很久,返回值 不能馬上獲取,那么就可以使用 Future Pattern。Future Pattern同樣會每個請求建立一個線程處理,同時會馬上返回一個對象,但該對象并不是真正的返回值,真正的返回值可能現在還沒有準備好,不過客戶端可 以根據這個返回對象,在之后的時間來獲取真正的返回值。
public?interface?Data?{
public?String?getContent();
}
public?class?RealData?implements?Data?{
private?String?content;
public?RealData(int?count,?char?c)?{
System.out.println("making?RealData("?+?count?+?",?"?+?c?+?")?Begin.");
char[]?buffer?=?new?char[count];
for?(int?i?=?0;?i?
buffer[i]?=?c;
slowly();
}
this.content?=?String.valueOf(buffer);
System.out.println("making?RealData("?+?count?+?",?"?+?c?+?")?End.");
}
@Override
public?String?getContent()?{
return?this.content;
}
private?void?slowly()?{
try?{
Thread.sleep(100);
}?catch?(InterruptedException?e)?{
}
}
}
public?class?FutureData?implements?Data?{
private?RealData?realData;
private?boolean??ready?=?false;
public?synchronized?void?setRealData(RealData?realData)?{
if?(ready)?{
return;
}
this.realData?=?realData;
this.ready?=?true;
notifyAll();
}
@Override
public?synchronized?String?getContent()?{
while?(!ready)?{
try?{
wait();
}?catch?(InterruptedException?e)?{
}
}
return?this.realData.getContent();
}
}
public?class?Host?{
public?Data?handle(final?int?count,?final?char?c)?{
System.out.println("handle?(?"?+?count?+?",?"?+?c?+?")?Begin.");
final?FutureData?futureData?=?new?FutureData();
new?Thread()?{
@Override
public?void?run()?{
RealData?realData?=?new?RealData(count,?c);
futureData.setRealData(realData);
}
}.start();
System.out.println("handle?(?"?+?count?+?",?"?+?c?+?")?End.");
return?futureData;
}
}
public?class?Main?{
public?static?void?main(String[]?args)?{
System.out.println("main?Begin.");
Host?host?=?new?Host();
Data?data1?=?host.handle(10,?'a');
Data?data2?=?host.handle(20,?'b');
Data?data3?=?host.handle(30,?'c');
System.out.println("main?other?job?Begin.");
try?{
Thread.sleep(2000);
}?catch?(InterruptedException?e)?{
}
System.out.println("main?other?job?End.");
System.out.println("data1?=?"?+?data1.getContent());
System.out.println("data2?=?"?+?data2.getContent());
System.out.println("data3?=?"?+?data3.getContent());
System.out.println("main?End.");
}
}
在Worker Thread Pattern中,我們討論過“方法調用”和“方法執行”的分離。而Future Pattern 分離了“準備返回值”和“使用返回值”。我們在Futtern Pattern中,可以看到設計模式Proxy Pattern的實現。
Two-Phase Termination Pattern
Two-Phase Termination
Pattern很簡單,但該模式提供了一種結束線程的優雅方法。java.lang.Thread類有一個用來強制結束掉線程的stop()方法。但是
stop方法已經不建議使用(deprecated),原因是stop()方法會使實例喪失安全性的保障。使用stop()方法時,線程會拋出
java.lang.ThreadDeath異常而馬上結束,即使該線程現在正在執行靈界區間(例如synchronized方法的中間),也會馬上結
束。
public?class?CountupThread?extends?Thread?{
private?boolean?isShutdown?=?false;
private?int?????count??????=?0;
@Override
public?void?run()?{
try?{
while?(isShutdown)?{
doWork();
}
}?catch?(InterruptedException?e)?{
}?finally?{
doShutdown();
}
}
public?void?shutdownReqeust()?{
this.isShutdown?=?true;
interrupt();
}
private?void?doShutdown()?{
System.out.println("doShutdown:?current?count?is?"?+?this.count);
}
private?void?doWork()?throws?InterruptedException?{
System.out.println("curren?count?is?"?+?++count);
Thread.sleep(500);
}
public?static?void?main(String[]?args)?{
System.out.println("main?Begin.");
CountupThread?countupThread?=?new?CountupThread();
countupThread.start();
try?{
Thread.sleep(100000);
}?catch?(InterruptedException?e)?{
}
System.out.println("main?:?shutdown?request.");
countupThread.shutdownReqeust();
System.out.println("main?:?join");
//?等待線程結束
try?{
countupThread.join();
}?catch?(InterruptedException?e)?{
}
System.out.println("main?End.");
}
}
Thread-Specific Storage Pattern
Thread-Specific Storage
Pattern就是“線程獨有的存儲庫”、“針對每個線程提供的內存空間”的意義。java.lang.ThreadLocal的實例可以想象成一種集合
架構(collection)或許會比較好理解。ThreadLocal的實例只有一個,管理多個對象。
public?class?Log?{
private?static?final?ThreadLocal?tsLogCollection?=?new?ThreadLocal();
public?static?void?println(String?s)?{
getTSLog().printWrite(s);
}
public?static?void?close()?{
getTSLog().close();
}
private?static?TSLog?getTSLog()?{
TSLog?tsLog?=?tsLogCollection.get();
//?如果線程時第一次調用,新建立新文件并注冊log
if?(tsLog?==?null)?{
tsLog?=?new?TSLog(Thread.currentThread().getName()?+?"-log.txt");
tsLogCollection.set(tsLog);
}
return?tsLog;
}
}
import?java.io.FileNotFoundException;
import?java.io.PrintWriter;
public?class?TSLog?{
private?PrintWriter?writer;
public?TSLog(String?filename)?{
try?{
this.writer?=?new?PrintWriter(filename);
}?catch?(FileNotFoundException?e)?{
}
}
public?void?printWrite(String?s)?{
writer.println(s);
}
public?void?close()?{
writer.println("===========End?of?log===========");
writer.close();
}
}
public?class?ClientThread?extends?Thread?{
public?ClientThread(String?name)?{
super(name);
}
@Override
public?void?run()?{
System.out.println(getName()?+?"?Begin.");
for?(int?i?=?0;?i?
Log.println("i?=?"?+?i);
try?{
Thread.sleep(100);
}?catch?(InterruptedException?e)?{
}
}
Log.close();
System.out.println(getName()?+?"?End.");
}
public?static?void?main(String[]?args)?{
new?ClientThread("Alice").start();
new?ClientThread("Bobby").start();
new?ClientThread("Chris").start();
}
}
Active Object Pattern
Active Object
Pattern其實可以看作是多個多線程模式和多個設計模式組合成的一種更高級的模式,里面多個對象各司其職,共同協作。Active Object
Pattern里面使用到了Producer-Consumer Pattern、Thread-Per-Message Pattern、Future
Pattern和設計模式的Proxy Pattern、Command Pattern等。
Server端代碼:
public?interface?ActiveObject?{
public?Result?makeString(int?count,?char?fillchar);
public?void?displayString(String?string);
}
public?class?Proxy?implements?ActiveObject?{
private?SchedulerThread?scheduler;
private?Servant?????????servant;
public?Proxy(SchedulerThread?scheduler,?Servant?servant)?{
this.scheduler?=?scheduler;
this.servant?=?servant;
}
@Override
public?Result?makeString(int?count,?char?fillchar)?{
FutureResult?future?=?new?FutureResult();
MakeStringRequest?request?=?new?MakeStringRequest(servant,?future,?count,?fillchar);
this.scheduler.invoke(request);
return?future;
}
@Override
public?void?displayString(String?string)?{
DisplayStringRequest?request?=?new?DisplayStringRequest(servant,?string);
this.scheduler.invoke(request);
}
}
public?class?Servant?implements?ActiveObject?{
@Override
public?Result?makeString(int?count,?char?fillchar)?{
char[]?buffer?=?new?char[count];
for?(int?i?=?0;?i?
buffer[i]?=?fillchar;
try?{
Thread.sleep(500);
}?catch?(InterruptedException?e)?{
}
}
RealResult?result?=?new?RealResult(String.valueOf(buffer));
return?result;
}
@Override
public?void?displayString(String?string)?{
System.out.println("displayString(?"?+?string?+?"?)");
try?{
Thread.sleep(10);
}?catch?(InterruptedException?e)?{
}
}
}
public?interface?Result?{
public?String?getResultValue();
}
public?class?FutureResult?implements?Result?{
private?Result??result;
private?boolean?isReady?=?false;
public?synchronized?void?setResult(Result?result)?{
if?(isReady)?{
return;
}
this.result?=?result;
this.isReady?=?true;
notifyAll();
}
@Override
public?synchronized?String?getResultValue()?{
while?(!isReady)?{
try?{
wait();
}?catch?(InterruptedException?e)?{
}
}
return?result.getResultValue();
}
}
public?class?RealResult?implements?Result?{
private?String?resultValue;
public?RealResult(String?resultValue)?{
this.resultValue?=?resultValue;
}
@Override
public?String?getResultValue()?{
return?this.resultValue;
}
}
public?abstract?class?MethodRequest?{
protected?final?Servant??????servant;
protected?final?FutureResult?future;
public?MethodRequest(Servant?servant,?FutureResult?future)?{
this.servant?=?servant;
this.future?=?future;
}
public?abstract?void?execute();
}
public?class?MakeStringRequest?extends?MethodRequest?{
private?int??count;
private?char?fillchar;
public?MakeStringRequest(Servant?servant,?FutureResult?future,?int?count,?char?fillchar)?{
super(servant,?future);
this.count?=?count;
this.fillchar?=?fillchar;
}
@Override
public?void?execute()?{
Result?result?=?this.servant.makeString(count,?fillchar);
future.setResult(result);
}
}
public?class?DisplayStringRequest?extends?MethodRequest?{
private?String?string;
public?DisplayStringRequest(Servant?servant,?String?string)?{
super(servant,?null);
this.string?=?string;
}
@Override
public?void?execute()?{
this.servant.displayString(string);
}
}
public?class?SchedulerThread?extends?Thread?{
private?ActivationQueue?queue?=?new?ActivationQueue();
public?void?invoke(MethodRequest?request)?{
this.queue.putRequest(request);
}
@Override
public?void?run()?{
while?(true)?{
this.queue.takeRequest().execute();
}
}
}
package?activeobject.server;
import?java.util.LinkedList;
public?class?ActivationQueue?{
private?final?LinkedList?requestQueue?=?new?LinkedList();
private?final?int???????????????????????queueSize????=?100;
public?synchronized?void?putRequest(MethodRequest?request)?{
while?(this.requestQueue.size()?>=?queueSize)?{
try?{
wait();
}?catch?(InterruptedException?e)?{
}
}
this.requestQueue.addLast(request);
notifyAll();
}
public?synchronized?MethodRequest?takeRequest()?{
while?(this.requestQueue.size()?==?0)?{
try?{
wait();
}?catch?(InterruptedException?e)?{
}
}
MethodRequest?request?=?this.requestQueue.removeFirst();
notifyAll();
return?request;
}
}
public?class?ActiveObjectFactory?{
public?static?ActiveObject?createActiveObjcet()?{
Servant?servant?=?new?Servant();
SchedulerThread?scheduler?=?new?SchedulerThread();
Proxy?proxy?=?new?Proxy(scheduler,?servant);
scheduler.start();
return?proxy;
}
}
UML如下圖:
客戶端代碼:
import?activeobject.server.ActiveObject;
public?class?DisplayClientThread?extends?Thread?{
private?ActiveObject?activeObj;
public?DisplayClientThread(String?name,?ActiveObject?activeObj)?{
super(name);
this.activeObj?=?activeObj;
}
@Override
public?void?run()?{
int?i?=?0;
while?(true)?{
i++;
String?string?=?getName()?+?"?No."?+?i;
activeObj.displayString(string);
}
}
}
import?activeobject.server.ActiveObject;
import?activeobject.server.Result;
public?class?MakerClientThread?extends?Thread?{
private?final?ActiveObject?activeObj;
private?final?char?????????fillchar;
public?MakerClientThread(String?name,?ActiveObject?activeObj)?{
super(name);
this.activeObj?=?activeObj;
this.fillchar?=?name.charAt(0);
}
@Override
public?void?run()?{
int?i?=?0;
while?(true)?{
i++;
Result?result?=?activeObj.makeString(i,?fillchar);
try?{
Thread.sleep(1000);
}?catch?(InterruptedException?e)?{
}
String?resultValue?=?result.getResultValue();
System.out.println(Thread.currentThread().getName()?+?":value?=?"?+?resultValue);
}
}
}
import?activeobject.server.ActiveObject;
import?activeobject.server.ActiveObjectFactory;
public?class?Main?{
public?static?void?main(String[]?args)?{
ActiveObject?activeObj?=?ActiveObjectFactory.createActiveObjcet();
new?MakerClientThread("Alice",?activeObj).start();
new?MakerClientThread("Bobby",?activeObj).start();
new?DisplayClientThread("Chris",?activeObj).start();
}
}
總結
以上是生活随笔為你收集整理的java 线程 设计模式_Java多线程设计模式(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用css制作二级下拉菜单
- 下一篇: 学习报告:基于原型网络的小样本学习《Pr