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

该模式的重点是,如果一个请求的资源状态还没有准备好,那么就不进行处理,直接返回,它与Guarded Suspension Pattern的区别在于Guarded Suspension Pattern在警戒条件不成立时,线程等待,而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多线程模式(二)的更多相关文章

  1. Java多线程(二)关于多线程的CPU密集型和IO密集型这件事

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  2. 简述Java多线程(二)

    Java多线程(二) 线程优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行. 优先级高的不一定先执行,大多数情况是这样的. 优 ...

  3. Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

    一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...

  4. java多线程系列(二)

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  5. java多线程系列(二)---对象变量并发访问

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  6. Java总结篇系列:Java多线程(二)

    本文承接上一篇文章<Java总结篇系列:Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法 ...

  7. java多线程基础(二)--java多线程的基本使用

    java多线程的基本使用 在java中使用多线程,是通过继承Thread这个类或者实现Runnable这个接口或者实现Callable接口来完成多线程的. 下面是很简单的例子代码: package c ...

  8. (Java多线程系列二)线程间同步

    Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...

  9. java多线程解读二(内存篇)

    线程的内存结构图 一.主内存与工作内存 1.Java内存模型的主要目标是定义程序中各个变量的访问规则.此处的变量与Java编程时所说的变量不一样,指包括了实例字段.静态字段和构成数组对象的元素,但是不 ...

随机推荐

  1. 编写一个循环将list容器的元素逆序输出

    <c++ primer>P270,习题9.9 实现代码如下: #include<iostream> #include<list> using namespace s ...

  2. Android之布局属性

    1) 布局的相关属性 ① android:layout_weight="1.0",layout_weight 用于给一个线性布局中的诸多视图重要度赋值.所有的视图都有一个layou ...

  3. HDU5739 Fantasia 树形dp + 点双缩点

    这个题当时打多校的时候有思路,但是代码能力差,没有写出来 事后看zimpha巨巨的题解,看了觉得基本差不多 核心思路:就是找出割点,然后变成森林,然后树形dp就可以搞了 关键就在重新构图上,缩完点以后 ...

  4. IOS CAShapeLayer CAGradientLayer UIBezierPath 使用实例

    CGRect rect = CGRectMake(100, 100, 100, 100); UIView * bgView = [[UIView alloc]initWithFrame:rect]; ...

  5. SSH超时断开(ClientAliveInterval和ClientAliveCountMax )的使用

    有 2个方法 1 配置服务器 打开 /etc/ssh/sshd_config 找到 ClientAliveInterval 参数,如果没有就自己加一行 数值是秒,比如你设置为300,就是5分钟. Cl ...

  6. Apache benchmark对网站进行压力测试

    Apache Benchmark下载:http://down.tech.sina.com.cn/page/3132.html ab 的全称是 ApacheBench , 是 Apache 附带的一个小 ...

  7. qt 获取天气的接口

    博客来源:http://blog.csdn.net/lzqwebsoft/article/details/7054045 网站api接口:http://smart.weather.com.cn/wzf ...

  8. 微信公众平台开发(57)Emoji表情符号

    微信公众平台开发 微信公众平台开发模式 企业微信公众平台 Emoji表情符号 作者:方倍工作室 地址:http://www.cnblogs.com/txw1958/p/crack-golden-egg ...

  9. document.write("\x3c\x54")?是加密了吗?

    <script>document.writeln("\x3C\x73\x63\x72\x69\x70\x74\x20\x73\x72\x63\x3D\x22\x48\x54\x5 ...

  10. CentOS安装XRDP实现远程桌面访问

    1.配置环境: yum install gcc pam-devel openssl-devel -y 2.进入指定目录下载并解压xrdp: 先安装 wget; sudo yum -y install ...