多线程开发的捷径:构建Java并发模型框架
14. try {
15. wait();
16. }catch (InterruptedException e) {
17. e.printStackTrace();
18. }
19. }
20.
21. _queue.push(mr);
22. notifyAll();
23. System.out.println("Leave Queue");
24. }
25. public synchronized MethodRequest dequeue() {
26. MethodRequest mr;
27.
28. while(_queue.empty()) {
29. try {
30. wait();
31. }catch (InterruptedException e) {
32. e.printStackTrace();
33. }
34. }
35. mr = (MethodRequest)_queue.pop();
36. notifyAll();
37.
38. return mr;
39. }
40. private Stack _queue;
41. private final static int QUEUE_SIZE = 20;
42.}
43.//ActiveObject的定义
44.class ActiveObject extends Thread
45.{
46. public ActiveObject() {
47. _queue = new ActiveQueue();
48. start();
49. }
50. public void enqueue(MethodRequest mr) {
51. _queue.enqueue(mr);
52. }
53. public void run() {
54. while(true) {
55. MethodRequest mr = _queue.dequeue();
56. mr.call();
57. }
58. }
59. private ActiveQueue _queue;
60.}
通过上面的代码可以看出正是这些类相互合作完成了对并发逻辑的封装。开发者只需要根据需要实现MethodRequest接口,另外再定义一个服务代理类提供给使用者,在服务代理者类中把服务调用者的请求转化为MethodRequest实现,交给活动对象即可。
使用该框架,可以较好的做到应用逻辑和并发模型的分离,从而使开发者集中精力于应用领域,然后平滑的和并发模型结合起来,并且可以针对ActiveQueue定制排队机制,比如基于优先级等。
基于框架的解决方案
本小节将使用上述的框架重新实现前面的例子,提供对于并发的支持。第一步先完成对于MethodRequest的实现,对于我们的例子来说实现如下:
1.class SayHello implements MethodRequest
2.{
3. public SayHello(Service s) {
4. _service = s;
5. }
6. public void call() {
7. _service.sayHello();
8. }
9. private Service _service;
10.}
该类完成了对于服务提供接口sayHello方法的封装。接下来定义一个服务代理类,来完成请求的封装、排队功能,当然为了做到对Client透明,该类必须实现Service接口。定义如下:
11.class ServiceProxy implements Service
12.{
13. public ServiceProxy() {
14. _service = new ServiceImp();
15. _active_object = new ActiveObject();
16. }
17.
18. public void sayHello() {
19. MethodRequest mr = new SayHello(_service);
20. _active_object.enqueue(mr);
21. }
22. private Service _service;
23. private ActiveObject _active_object;
24.}
其他的类和接口定义不变,下面对比一下并发逻辑增加前后的服务调用的变化,并发逻辑增加前,对于sayHello服务的调用方法:
25.Service s = new ServiceImp();
26.Client c = new Client(s);
27.c.requestService();
并发逻辑增加后,对于sayHello服务的调用方法:
28.Service s = new ServiceProxy();
29.Client c = new Client(s);
30.c.requestService();
可以看出并发逻辑增加前后对于Client的ServiceImp都无需作任何改变,使用方式也非常一致,ServiceImp也能够独立的进行重用。类结构图如下: