Java多线程模式(二)
Guarded Suspension Pattern
public class Request {
private Stringname;
public Request(String name) {
this.name = name;
}
public String getName() {
returnname;
}
@Override
public String toString() {
return"[ Request " +name +" ]";
}
}
public class RequestQueue {
final private LinkedList<Request>queue = new LinkedList<Request>();
public synchronizedvoid putRequest(Request request) {
this.queue.addLast(request);
notifyAll();
}
publicsynchronized Request getRequest() {
// 多线程版本的if
while (this.queue.size() <= 0) {
try {
wait();
}catch (InterruptedException e) {
}
}
return queue.removeFirst();
}
}
import java.util.Random;
public class ClientThreadextends Thread {
private Random random;
private RequestQueuerequestQueue;
public ClientThread(RequestQueue requestQueue, String name,long seed) {
super(name);
this.requestQueue = requestQueue;
this.random =new Random(seed);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Request request = new Request("No." + i);
System.out.println(Thread.currentThread().getName() +" requests " + request);
this.requestQueue.putRequest(request);
try {
Thread.sleep(this.random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
import java.util.Random;
public class ServerThreadextends Thread {
private Random random;
private RequestQueuequeue;
public ServerThread(RequestQueue queue, String name,long seed) {
super(name);
this.queue = queue;
random =new Random(seed);
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Request request = queue.getRequest();
System.out.println(Thread.currentThread().getName() +" handles " + request);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
publicclass Main {
public static void main(String[] args) {
RequestQueue queue = new RequestQueue();
ServerThread serverThread = new ServerThread(queue,"ServerThread", 3141592l);
ClientThread clientThread = new ClientThread(queue,"ClientThread", 6535897l);
serverThread.start();
clientThread.start();
}
}
这段代码的关键在ReqeustQueue类的getReqeust()方法,在该方法中,判断队列是否小于或等于0,如果是,那么就等待队列有数据之后在进行获取Request对象的操作,注意这里使用的是while,而非if。Single Threaded Execution Pattern 只有一个线程可以进入临界区,其他线程不能进入,进行等待;而Guarded Suspension Pattern中,线程要不要等待,由警戒条件决定。只有RequestQueue类使用到了wait/notifyAll,Guarded Suspension Pattern的实现是封闭在RequestQueue类里的。
Balking Pattern
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
publicclass Data {
private final Stringfilename;
private String content;
privateboolean changed;
public Data(String filename, String content) {
this.filename = filename;
this.content = content;
this.changed =true;
}
public synchronizedvoid change(String content) {
this.content = content;
this.changed =true;
}
publicsynchronizedvoid save() {
while (!this.changed) {
return;
}
doSave();
this.changed =false;
}
private void doSave() {
System.out.println(Thread.currentThread().getName() +"calls doSave, content = "
+ this.content);
File file = new File(filename);
FileWriter writer = null;
try {
writer = new FileWriter(file, true);
writer.write(this.content);
} catch (IOException e) {
} finally {
if (writer !=null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
import java.util.Random;
public class ChangerThreadextends Thread {
private Data data;
private Randomrandom =new Random();
public ChangerThread(String name, Data data) {
super(name);
this.data = data;
}
@Override
public void run() {
int i = 0;
while (true) {
i++;
String content = "No." + i;
this.data.change(content);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
this.data.save();
}
}
}
import java.util.Random;
public class SaverThreadextends Thread {
private Data data;
private Randomrandom =new Random();
public SaverThread(String name, Data data) {
super(name);
this.data = data;
}
@Override
public void run() {
while (true) {
this.data.save();
try {
Thread.sleep(this.random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args) {
Data data = new Data("data.txt","(empty)");
new SaverThread("SaverThread", data).start();
new ChangerThread("ChangerThread", data).start();
}
}
Producer-Consumer Pattern
import java.io.Serializable;
public class Data implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7212370995222659529L;
private String name;
public Data(String name) {
this.name = name;
}
@Override
public String toString() {
return"[ Data name = " +this.name +" ]";
}
}
import java.util.LinkedList;
/**
* 数据传输channel,默认大小100,可以通过构造函数定制channel的大小。channel为FIFO模型
*/
public class Channel {
private final LinkedList<Data>buffer =new LinkedList<Data>();
private int bufferSize = 100;
public Channel() {
super();
}
public Channel(int channelSize) {
this.bufferSize = channelSize;
}
/**
* put数据到channel中,当channel的buffer大小大于或等于指定大小时,方法将进行等待
*
* @param data
*/
public synchronizedvoid put(Data data) {
while (buffer.size() >=this.bufferSize) {
try {
wait();
} catch (InterruptedException e) {
}
}
this.buffer.addLast(data);
System.out.println(Thread.currentThread().getName() +" put data " + data);
notifyAll();
}
/**
* 从channel中获取数据,当channel中没有数据时,进行等待
*
* @return
*/
public synchronized Data take() {
while (this.buffer.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
Data data = this.buffer.removeFirst();
System.out.println(Thread.currentThread().getName() +" take date " + data);
notifyAll();
return data;
}
}
import java.util.Random;
public class ComsumerThreadextends Thread {
private Channel channel;
private Random random =new Random();
public ComsumerThread(String name, Channel channel) {
super(name);
this.channel = channel;
}
@Override
public void run() {
while (true) {
this.channel.take();
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
import java.util.Random;
public class ProducerThreadextends Thread {
private Channel channel;
private Random random =new Random();
privatestaticintdataNo = 0;
public ProducerThread(String name, Channel channel) {
super(name);
this.channel = channel;
}
@Override
public void run() {
while (true) {
Data data = new Data("No." + nextDataNo());
this.channel.put(data);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
publicstaticsynchronizedint nextDataNo() {
return ++dataNo;
}
}
public class MainThread {
public static void main(String[] args) {
int channelSize = 1000;
Channel channel = new Channel(channelSize);
ProducerThread producer1 = new ProducerThread("Producer1", channel);
ProducerThread producer2 = new ProducerThread("Producer2", channel);
ComsumerThread comsumer1 = new ComsumerThread("Comsumer1", channel);
ComsumerThread comsumer2 = new ComsumerThread("Comsumer2", channel);
ComsumerThread comsumer3 = new ComsumerThread("Comsumer3", channel);
producer1.start();
producer2.start();
comsumer1.start();
comsumer2.start();
comsumer3.start();
}
}
Java多线程模式(二)的更多相关文章
- Java多线程(二)关于多线程的CPU密集型和IO密集型这件事
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
- 简述Java多线程(二)
Java多线程(二) 线程优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行. 优先级高的不一定先执行,大多数情况是这样的. 优 ...
- Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)
一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...
- java多线程系列(二)
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- java多线程系列(二)---对象变量并发访问
对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...
- Java总结篇系列:Java多线程(二)
本文承接上一篇文章<Java总结篇系列:Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法 ...
- java多线程基础(二)--java多线程的基本使用
java多线程的基本使用 在java中使用多线程,是通过继承Thread这个类或者实现Runnable这个接口或者实现Callable接口来完成多线程的. 下面是很简单的例子代码: package c ...
- (Java多线程系列二)线程间同步
Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...
- java多线程解读二(内存篇)
线程的内存结构图 一.主内存与工作内存 1.Java内存模型的主要目标是定义程序中各个变量的访问规则.此处的变量与Java编程时所说的变量不一样,指包括了实例字段.静态字段和构成数组对象的元素,但是不 ...
随机推荐
- redhat--nagios插件--check_traffic.sh
****在被监控主机安装nrpe**** (1)在被监控主机上,增加用户和密码 useradd nagios passwd nagios (2)安装nagios插件 tar zxf nagios-pl ...
- Javascript Utils.js
\ var Utils ={//字符串格式化StringFormat: function () {if (arguments.length == 0)return null;var str = arg ...
- ECshop 二次开发模板教程1
本教程适用于了解 ECshop 和 ECshop模板DIY 以及它们的日常使用,在查看前阁下需要至少会使用一种编辑器(exp:Dreamweaver, editplus, emacs, vi, ee ...
- POJ 3621 Sightseeing Cows 01分数规划,最优比例环的问题
http://www.cnblogs.com/wally/p/3228171.html 题解请戳上面 然后对于01规划的总结 1:对于一个表,求最优比例 这种就是每个点位有benefit和cost,这 ...
- NSThread 多线程相关
1.下面的代码,有2点需要注意,1>就是 就是thread:所传得参数,这里传得的是nsarray 当然也可以传其他的类型.2> [self performSelectorOnMainTh ...
- Tableau学习笔记之五
计算用户自定义字段,虽然在Tableau软件中已经加入了很多的数值操作运算,比如平均值,最大值等,但是可以自定义自己需要的数值操作运算. 数值操作可以有以下:预定义函数,百分比,总计,分级等等 1.直 ...
- JDBC中DAO事务函数模版
DAO事物函数模版1: public void OrderFinsByPage(){ Connection conn = null; PreparedStatement pstmt = null; R ...
- bzoj 3698 XWW的难题(有源汇的上下界最大流)
[题意] 对每个格子确定上下取整,使得满足1.A[n][n]=0 2.每行列前n-1个之和为第n个 3.格子之和尽量大. [思路] 设格子(i,j)上下取整分别为up(i,j)down(i,j),构图 ...
- HDU4869:Turn the pokers(快速幂求逆元+组合数)
题意: 给出n次翻转和m张牌,牌相同且一开始背面向上,输入n个数xi,表示xi张牌翻转,问最后得到的牌的情况的总数. 思路: 首先我们可以假设一开始牌背面状态为0,正面则为1,最后即是求ΣC(m,k) ...
- Hadoop Hive概念学习系列之为什么Hive里,要用mysql?(四)
想说的是,hive只是个工具,包括它的数据分析,依赖于mapreduce,它的数据管理,依赖于外部系统. metastore_db,是在哪目录下运行,在哪里产生数据. 由此可见,你在哪路径下,执行hi ...