多线程学习之三生产者消费者模式Guarded Suspension

Guarded Suspension【生产消费者模式】

一:guarded suspension的参与者
--->guardedObject(被防卫)参与者
                1.1该参与者拥有一个被防卫的方法(getRequest),如果警戒条件达成,则执行。警戒条件不达成,则线程进入wait set
                1.2该参与者还拥有一个改变参与者状态的方法(putRequest)。参与者的状态影响着警戒条件的是否达成。

--->该模式的角色:生产端线程,消费端线程,传递数据的摇篮(被防卫的参与者)
       

二:guarded suspension模式什么时候使用
--->适合交易系统使用。客户端下单,服务端处理订单。高并发,大量数据处理的模式,增强服务的吞吐量
   

三:guarded suspension思考
--->与该模式共通的三个特征
                3.1:有循环存在
                3.2:有条件测试
                3.3:有因某种原因的等待

---> guarded wait 被阻断而等待
        等待端范例:
        while(条件){
                wait();
        }
        唤醒端范例:
                条件=true
                notifyAll();
---> busy wait 忙碌地等待
        yield,尽可能把优先级交给其他线程,那个线程调用此方法,那个线程暂时一次让出CPU调度权。至于能否暂停,实际看cpu是否去掉别的线程。我主动 放弃一次,至于cpu走不走,看cpu的。yield不会解除锁定,所以这段代码不可写在snychronized里。而ready字段必须声明成 volatile
        等待端范例:
        while(ready){
                Thead.yield();
        }
        唤醒端范例:
        ready=true

---> spin lock 旋转而锁定
        旋转而锁定的意思,表现出条件成立前while循环不断"旋转"的样子,spin lock有时意思与guarded wait相同,有时则与busy wait相同。另外,有时候则是指一开始使用busy wait ,之后再切换成guarded wait方式。另外有些硬件实现的同步机制

--->polling
" 进行舆论调查"的意思,反复检查某个事件是否发生,当发生时就进行对应的处理。

请求实体类

 1 /**
 2  * 
 3  */
 4 package com.benxq.thread4;
 5 
 6 /**
 7  * 模拟请求实体
 8  * Created by qucf on 2015年10月22日. 
 9  */
10 public class RequestEntity {
11 
12     //请求人的名称
13     private String name;
14     
15     //线程的名称
16     private String clientThreadName;
17 
18     
19     public RequestEntity() {
20         super();
21     }
22 
23     /**
24      * @param name
25      * @param clientThreadName
26      */
27     public RequestEntity(String name, String clientThreadName) {
28         super();
29         this.name = name;
30         this.clientThreadName = clientThreadName;
31     }
32 
33     public String getName() {
34         return name;
35     }
36 
37     public void setName(String name) {
38         this.name = name;
39     }
40 
41     public String getClientThreadName() {
42         return clientThreadName;
43     }
44 
45     public void setClientThreadName(String clientThreadName) {
46         this.clientThreadName = clientThreadName;
47     }
48     
49     @Override
50     public String toString() {
51         return "生产者:"+clientThreadName+"生产者生产的产品"+name+"被消费";
52     }
53 }
View Code

请求实体队列类

 1 /**
 2  * 
 3  */
 4 package com.benxq.thread4;
 5 
 6 import java.util.LinkedList;
 7 
 8 /**
 9  * 模拟请求队列
10  * Created by qucf on 2015年10月22日. 
11  */
12 public class RequestQueue {
13 
14     //模拟队列容器
15     private LinkedList<RequestEntity> list=new LinkedList<RequestEntity>();
16     
17     //从队列中取出数据
18     public synchronized RequestEntity getRequestEntity(){
19         //当容器中的数据为0时进入等待状态
20         while(list.size()<=0){
21             try {
22                 wait();
23             } catch (InterruptedException e) {
24                 // TODO Auto-generated catch block
25                 e.printStackTrace();
26             }
27         }
28         //如果不为空,返回第一个请求,并从集合中删除该请求
29         return list.removeFirst();
30     }
31     
32     //往队列中加入数据
33     public synchronized void putRequestEntity(RequestEntity entity){
34         //将加入的数据加入队列尾部
35         list.addLast(entity);
36         //唤醒所有的线程
37         notifyAll();
38     }
39     
40 }
View Code

生产线程

 1 /**
 2  * 
 3  */
 4 package com.benxq.thread4;
 5 
 6 import java.util.Random;
 7 
 8 /**
 9  * 模拟请求线程
10  * Created by qucf on 2015年10月22日. 
11  */
12 public class ClientThread implements Runnable{
13 
14     //存放请求的队列
15     private RequestQueue queue;
16     
17     //随机数
18     private Random random;
19     
20     //线程名称
21     private String name;
22 
23     
24 
25     /**
26      * @param queue
27      * @param random
28      * @param name
29      */
30     public ClientThread(RequestQueue queue, Random random, String name) {
31         super();
32         this.queue = queue;
33         this.random = random;
34         this.name = name;
35     }
36 
37 
38 
39     @Override
40     public void run() {
41 
42         for (int i = 0; i < 5; i++) {
43             //生成一个请求
44             RequestEntity entity=new RequestEntity("No"+i, name);
45             
46             //将请求放入到队列中
47             queue.putRequestEntity(entity);
48             
49             //让线程休息几秒
50             try {
51                 Thread.sleep(1000);
52             } catch (InterruptedException e) {
53                 // TODO Auto-generated catch block
54                 e.printStackTrace();
55             }
56         }
57     }
58 }
View Code

消费线程

 1 /**
 2  * 
 3  */
 4 package com.benxq.thread4;
 5 
 6 import java.util.Random;
 7 
 8 /**
 9  * 消费线程
10  * Created by qucf on 2015年10月22日. 
11  */
12 public class ServiceThread implements Runnable{
13 
14     //持有线程的队列
15     private RequestQueue queue;
16     //随机数
17     private Random random;
18     //线程名
19     private String name;
20     
21     @Override
22     public void run() {
23         while(true){
24             RequestEntity entiry=queue.getRequestEntity();
25             System.out.println("消费线程"+name+"----->"+entiry.toString());
26             try {
27                 Thread.sleep(random.nextInt(random.nextInt(1000)));
28             } catch (InterruptedException e) {
29                 // TODO Auto-generated catch block
30                 e.printStackTrace();
31             }
32         }
33     }
34 
35     /**
36      * @param queue
37      * @param random
38      * @param name
39      */
40     public ServiceThread(RequestQueue queue, Random random, String name) {
41         super();
42         this.queue = queue;
43         this.random = random;
44         this.name = name;
45     }
46 
47     
48 }
View Code

主线程

 1 /**
 2  * 
 3  */
 4 package com.benxq.thread4;
 5 
 6 import java.util.Random;
 7 
 8 /**
 9  * 主线程
10  * Created by qucf on 2015年10月22日. 
11  */
12 public class Test {
13 
14     
15     public static void main(String[] args) {
16         //声明一个队列
17         RequestQueue queue=new RequestQueue();
18         
19         //生产者线程
20         Thread sc1=new Thread(new ClientThread(queue, new Random(), "QQ客户端"));
21         Thread sc2=new Thread(new ClientThread(queue, new Random(), "ALIBABA客户端"));
22         
23         //消费者线程
24         Thread xf1=new Thread(new ServiceThread(queue, new Random(), "渠道1"));
25         Thread xf2=new Thread(new ServiceThread(queue, new Random(), "渠道2"));
26         Thread xf3=new Thread(new ServiceThread(queue, new Random(), "渠道3"));
27         
28         //开启线程
29         sc1.start();
30         sc2.start();
31         
32         xf1.start();
33         xf2.start();
34         xf3.start();
35     }
36 }
View Code
原文地址:https://www.cnblogs.com/quchengfeng/p/4901552.html