多线程程序设计学习(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的参与者--->产品(蛋糕)--->通道(传递蛋糕的桌子)--->生产者线程 ...
随机推荐
- LoadRunner 11 安装及破解(转)
前提条件: 内存:2G,硬盘空闲空间10G,安装完成后实际只占不到2G 支持winXP SP3;32位与64位win7浏览器支持IE6-8,IE9,firefox3 若以前安装过LoadRunner ...
- UVALive 6525
二分图最大匹配 #include<cstdio> #include<iostream> #include<cstring> #define MAX 10010 us ...
- java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@450b2f48 异常处理
晕死的错误,改了半天也没想到是这样的原因,基础正要呀... 先看一下警告信息: 07-07 08:32:19.540: WARN/WindowManager(74): Failed looking u ...
- docker设置代理
在天朝使用docker需要FQ. 下面给出docker的代理方式: HTTP_PROXY=http://10.167.251.83:8080 docker -d
- 利用vim阅读源代码一个好用的工具
阅读源代码时常常遇到找变量,函数定义的问题.vim为我们提供了一个好用的工具,ctags. 安装 ctags. 在 libvirt的源代码根目录运行 ctags -R . vim -t virConn ...
- BFS 模板
转自:欣哥 下面是bfs一般的形式,谈不上模板但一般都这么来做有点乱有什么多交流 bfs一般用于求最短时间 #include<stdio.h>#include<queue>us ...
- 【memcache缓存专题(1)】memcache的介绍与应用场景
简介 Memcached是一个高性能的分布式的内存对象缓存系统,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各 ...
- Android:控件的隐藏显示
布局中的:android:visibility 程序中可用setVisibility(); 对应的三个常量值:0.4.8 VISIBLE:0 意思是可见的INVISIBILITY:4 意思是不可见的, ...
- 在C#中怎么调用Resources文件中的图片
譬如资源中有名为myPic的图片,在代码中可以这么使用: this.BackgroundImage = Properties.Resources.myPic; 如有疑问,继续追问.
- *EditPlus注册码在线生成
http://www.jb51.net/tools/editplus/