多线程程序设计学习(4)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
" 进行舆论调查"的意思,反复检查某个事件是否发生,当发生时就进行对应的处理。
模仿队列(传递数据)
package com.yeepay.sxf.thread3; import java.util.LinkedList; /**
* 存放实体的队列
* @author sxf
*
*/
public class RequestEntryQueue {
//存放请求的链表集合
private final LinkedList<RequestEntry> list=new LinkedList<RequestEntry>(); //从队列中取出请求
public synchronized RequestEntry getRequestEntry(){
//判断存放请求的集合是否存在,请求,不存在,就让当前消费着线程进入wait set
while (list.size()<=0) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
//如果不为空,则返回第一个请求,并从集合中删除该请求
return list.removeFirst();
} //往队列中放入请求
public synchronized void putRequestEntry(RequestEntry requestEntry){
//将新的请求放入队列
list.addLast(requestEntry);
//唤醒所有wait set中的线程
notifyAll();
}
}
请求实体
package com.yeepay.sxf.thread3;
/**
* 请求实体
* @author sxf
*
*/
public class RequestEntry {
//请求人的名字
private String name;
//线程的名字
private String clientThreadName; public RequestEntry() {
super();
} @Override
public String toString() {
// TODO Auto-generated method stub
return "["+clientThreadName+"生产线程]生产的商品"+name+"被消费";
} public RequestEntry(String name,String clientThreadName) { this.name = name;
this.clientThreadName=clientThreadName; } public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getClientThreadName() {
return clientThreadName;
} public void setClientThreadName(String clientThreadName) {
this.clientThreadName = clientThreadName;
} }
客户端线程
package com.yeepay.sxf.thread3; import java.util.Random; /**
* 客户端线程
* @author sxf
*
*/
public class ClientThread implements Runnable{
//存放请求的队列
private RequestEntryQueue requestEntryQueue;
//随即数
private Random random;
//线程名字
private String name; //构造器
public ClientThread(RequestEntryQueue requestEntryQueue, Random random,String name) {
super();
this.requestEntryQueue = requestEntryQueue;
this.random = random;
this.name=name;
} @Override
public void run() {
for(int i=0;i<1000;i++){
//生成一个请求
RequestEntry requestEntry=new RequestEntry("No"+i,name);
//将该请求存入队列
requestEntryQueue.putRequestEntry(requestEntry);
//让线程休息几秒
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } }
服务端线程
package com.yeepay.sxf.thread3; import java.util.Random; /**
* 服务线程
* @author sxf
*
*/
public class ServiceThread implements Runnable{
//持有存放请求的队列
private RequestEntryQueue requestEntryQueue;
//随即数
private Random random;
//线程名字
private String name; public ServiceThread(RequestEntryQueue requestEntryQueue, Random random,
String name) {
super();
this.requestEntryQueue = requestEntryQueue;
this.random = random;
this.name = name;
} @Override
public void run() {
while(true){
RequestEntry requestEntry=requestEntryQueue.getRequestEntry();
System.out.println("【消费者线程"+name+"】----------->"+requestEntry.toString()); try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } }
测试类
package com.yeepay.sxf.thread3; import java.util.Random; /**
* 测试类
* @author sxf
*
*/
public class Test { public static void main(String[] args) {
//声明一个队列
RequestEntryQueue requestEntryQueue=new RequestEntryQueue();
//声明两个生产者线程
Thread clientThread1=new Thread(new ClientThread(requestEntryQueue, new Random(), "QQ客户端"));
Thread clientThread2=new Thread(new ClientThread(requestEntryQueue, new Random(), "ALIBABA客户端"));
//声明三个消费者线程
Thread serviceThread1=new Thread(new ServiceThread(requestEntryQueue, new Random(), "易宝支付"));
Thread serviceThread2=new Thread(new ServiceThread(requestEntryQueue, new Random(), "支付宝"));
Thread serviceThread3=new Thread(new ServiceThread(requestEntryQueue, new Random(), "财付通"));
//开启线程
clientThread1.start();
clientThread2.start(); serviceThread1.start();
serviceThread2.start();
serviceThread3.start(); }
}
多线程程序设计学习(4)guarded suspension模式的更多相关文章
- 多线程系列之四:Guarded Suspension 模式
一,什么是Guarded Suspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待.这种模式通过让线程等待来保证实例的安全性 二,实现一个简单的线程间通信的例子 一个线程(Clie ...
- 多线程同步循环打印和Guarded suspension 模式
* 迅雷笔试题: * 有三个线程ID分别是A.B.C,请有多线编程实现,在屏幕上循环打印10次ABCABC… 由于线程执行的不确定性,要保证这样有序的输出,必须控制好多线程的同步. 线程同步有两种 ...
- 并发设计模式之Guarded Suspension模式
- 原文链接: http://www.joyhwong.com/2016/11/19/并发设计模式之guarded-suspension模式/ Guarded Suspension意为保护暂停,其核心 ...
- 并行模式之Guarded Suspension模式
并行模式之Guarded Suspension模式 一).Guarded Suspension: 保护暂存模式 应用场景:当多个客户进程去请求服务进程时,客户进程的请求速度比服务进程处里请求的速度快, ...
- 多线程程序设计学习(5)balking模式和timed模式
Balking[返回模式]timed[超时模式]一:balking pattern的参与者--->GuardedObject(被警戒的对象) --->该模式的角色:模拟修改警戒对象的线程, ...
- 多线程程序设计学习(2)之single threaded execution pattern
Single Threaded Execution Pattern[独木桥模式] 一:single threaded execution pattern的参与者--->SharedResourc ...
- Guarded Suspension模式简单实现
Guarded Suspension 意为保护暂停,假设服务器很短时间内承受大量的客户端请求,客户端请求的数量超过服务器本身的即时处理能力,而服务器又不能丢弃任何一个客户端请求,此时可以让客户端的请求 ...
- 多线程程序设计学习(3)immutable pattern模式
Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者 1.1:immutable参与者是一个 ...
- 多线程程序设计学习(6)Producer-Consumer模式
Producer-Consumer[生产消费者模式]一:Producer-Consumer pattern的参与者--->产品(蛋糕)--->通道(传递蛋糕的桌子)--->生产者线程 ...
随机推荐
- pureftpd安装配置-pureftp参数详解(一)
1. 下载 #cd /usr/local/src/ #wget ftp://ftp.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.30.tar.g ...
- Codeforces Round #363 (Div. 2)->B. One Bomb
B. One Bomb time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- PHP中$_SERVER获取当前页面的完整URL地址
PHP中$_SERVER获取当前页面的完整URL地址,其实很简单,主要是通过$_SERVER超全局变量来实现的. 具体PHP中$_SERVER获取当前页面的完整URL地址如下. #测试网址: ...
- Properties --- C++读配置信息的类
http://blog.csdn.net/billow_zhang/article/details/4304980 在开发实践中,积累了一些通用的C++ 类库,在此写出来给大家分享.也希望能给出更好的 ...
- winform Chart控件 获取鼠标处坐标值方法
Chart控件本身功能强大,应用广泛,因此其属性.方法也很多.此处介绍在很多应用中需要查看鼠标位置处坐标值的一些方法 1,调用Chart事件 GetToolTip 利用ToolTipEventArg ...
- POJ 2823 Sliding Window (线段树/单调队列)
题目不说了,可以用线段树或者单调队列,下面附上代码. 线段树: #include <iostream> #include <stdio.h> #include <algo ...
- POJ 3278Catch That Cow
http://poj.org/problem?id=3278 大意是说牛在原地不动,他在某点去抓牛,他有两种方式可以走,第一种走一步,往前往后都可,第二种是走现在所在点的两倍的数目.只要能够刚好到达牛 ...
- keystonejs
开始之前先确保你已经安装了Node.js 0.10+ 和MongoDB v2.4+. 要使用KeystoneJS,你需要掌握合理的Javascript知识,并熟悉数据库概念之类的基础知识,会用 nod ...
- *[codility]MissingInteger
今天开始刷刷codility上respectable的题目,难度适中. https://codility.com/demo/take-sample-test/missing_integer 本题是找出 ...
- HTML5入门1---Canvas画布
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...