Balking【返回模式】timed【超时模式】
一:balking pattern的参与者
--->GuardedObject(被警戒的对象)

--->该模式的角色:模拟修改警戒对象的线程,当警戒条件达到执行具体操作的线程,参与者(被警戒的参与者)

二:balking pattern模式什么时候使用
--->不需要刻意去执行什么操作的时候(比如说自动保存)
--->不想等待警戒条件成立时。(不让线程休息)
--->警戒条件只有第一次成立时候。

三:balking pattern思考
--->balking pattern (返回模式)和Guarded suspension pattern(等待唤醒模式)的中间
        3.1Guarded suspension当警戒条件不成立时,会等待,直到成立,并被唤醒。
        3.2balking 当警戒条件不成立,退出。
        3.3两种极端的处理方式之间还有一种折衷的做法。在条件成立为止之前,等待一段时间,看看条件是否成立,如果不成立,则balk。这种方式称之为guarded timed 或简单称之为timeOut
---->线程类中的各个唤醒方法
        3.1:当notify方法执行时==>如果wait set里有多条线程,只有一条被唤醒
        3.2:当notifyAll方法执行时==>wait set里有多少条线程都被唤醒。
        3.3:interrupt方法执行时==>wait set里的线程会(与调用notify,notifyAll一样)重新尝试获取锁定。
                                                       ==> notify,notifyAll是对实例调用的,而interrupt是对线程调用的。关于中断,后续会提到。
        3.4:发生timeout时,由于wait(超时时间),和被notify或notifyAll唤醒重新尝试获取锁定,分不清楚,所以timeout需要程序员自己写。

---->sleep和wait的区别有:
  1,这两个方法来自不同的类分别是Thread和Object
  2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
  3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
    任何地方使用
   synchronized(x){
      x.notify()
     //或者wait()
   }
   4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
   5.wait被唤醒后,重新获取锁,从阻塞的代码处继续往下执行。和sleep一样。

Balking【返回模式】案例:模拟自动保存文件,当文件没有更改时,每隔一秒的自动保存数据,真正保存操作不执行。如果有修改,则执行真正保存操作。

数据类

 package com.yeepay.sxf.thread4;

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; /**
* 数据类。
* @author sxf
*
*/
public class Data {
//文件名
private String fileName;
//文件内容
private String content;
//表示是否被修改过
private boolean flag;
//构造器
public Data(String fileName, String content) {
super();
this.fileName = fileName;
this.content = content;
this.flag=true;
File file =new File(fileName);
try {
file.createNewFile();
FileOutputStream iFileOutputStream=new FileOutputStream(file);
iFileOutputStream.write(content.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//修改内容
public synchronized void channgeContent(String newContent){
this.content=newContent ;
flag=true;
} //把新的数据写入文件
private void save() throws IOException{
System.out.println("Data.save()"+Thread.currentThread().getName()+"执行写入操作,写入的内容为:"+content);
FileOutputStream fileWriter=new FileOutputStream(new File(fileName));
fileWriter.write(content.getBytes());
} //保存内容
public synchronized void saveNewContent(){
if(!flag){
System.out.println("Data.saveNewContent(试图新保存,但没有更改)");
return;
}
try {
save();
System.out.println("Data.saveNewContent(新内容保存成功)");
flag=false;
} catch (IOException e) {
e.printStackTrace();
}
}
}

模拟修改数据的线程

 package com.yeepay.sxf.thread4;
/**
* 模拟自动修改线程
* @author sxf
*
*/
public class ChangeThread implements Runnable{
private Data data; public ChangeThread(Data data) {
super();
this.data = data;
} @Override
public void run() {
for(int i=0;i<20;i++){
//修改内容
System.out.println("ChangeThread.run()"+Thread.currentThread().getName()+"第"+i+"次修改");
data.channgeContent("新内容"+i);
//线程休息10秒
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }

模拟自动保存的线程

 package com.yeepay.sxf.thread4;
/**
* 自动保存的线程
* @author sxf
*
*/
public class ZiDongSaveThread implements Runnable{
private Data data; public ZiDongSaveThread(Data data){
this.data=data;
}
@Override
public void run() {
while(true){
//保存数据
data.saveNewContent();
//线程休息1秒,意味着每隔一妙钟自动保存一次文件
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } }

测试类

 package com.yeepay.sxf.thread4;
/**
* 测试类
* @author sxf
*
*/
public class Test { public static void main(String[] args) {
//声明内容
Data data=new Data("/usr/war/hsl.txt", "老黄买了新手机");
//声明自动保存线程
Thread saveThread=new Thread(new ZiDongSaveThread(data));
saveThread.setName("自动保存线程");
//声明模拟修改线程
Thread chaThread=new Thread(new ChangeThread(data));
chaThread.setName("模拟修改线程"); //启动线程
saveThread.start();
chaThread.start(); }
}

打印结果

Data.save()自动保存线程执行写入操作,写入的内容为:老黄买了新手机
Data.saveNewContent(新内容保存成功)
ChangeThread.run()模拟修改线程第0次修改
Data.save()自动保存线程执行写入操作,写入的内容为:新内容0
Data.saveNewContent(新内容保存成功)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
ChangeThread.run()模拟修改线程第1次修改
Data.save()自动保存线程执行写入操作,写入的内容为:新内容1
Data.saveNewContent(新内容保存成功)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)
Data.saveNewContent(试图新保存,但没有更改)

timed【超时模式】案例:一个线程提供下载数据,另一个线程执行下载,如果有5秒钟以上,提供下载的线程没有提供数据,下载线程因超时异常,停止下载线程运行。

超时异常类

 package com.yeepay.sxf.thread4;
/**
* 超时异常类
* @author sxf
*
*/
public class TimeOutException extends InterruptedException { public TimeOutException(String msg){
super(msg);
}
}

下载数据的数据类

 package com.yeepay.sxf.thread4;
/**
* 下载数据类
* @author sxf
*
*/
public class FileData {
//提供下载的数据
private String data;
//有数据可下载
private boolean flag;
//超时时间
private long timeout; //构造器
public FileData(String data, boolean flag, long timeout) {
super();
this.data = data;
this.flag = flag;
this.timeout = timeout;
} //修改状态,唤醒其他所有线程
public synchronized void changeStatus(String data){
this.data=data;
flag=true;
notify();
} //下载操作。如果等timeout/1000秒钟,没有数据供下载,就报超时异常,终止下载
public synchronized void execu() throws InterruptedException{
//开始执行的时间
long start=System.currentTimeMillis();
int i=0;
System.out.println("FileData.execu(开始时间1)");
while (!flag) {
//现在的时间
long now=System.currentTimeMillis();
long reset=timeout-(now-start);
if(reset<=0){
throw new TimeOutException("已经等候"+timeout+"时间了还没有数据可供下载,超时");
}
//如果没有超时,就让下载线程进入wait set,设置超时时间。被唤醒,继续从这里开始执行。
wait(reset);
}
//真正的下载操作
download();
} //真正的下载操作
private void download(){
System.out.println("顺利下载数据==>:"+data);
//下载完之后,将下载状态改为不可下载,等待放入新数据供下载
this.flag=false;
} public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
} public long getTimeout() {
return timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
}

提供数据供下载的线程类

 package com.yeepay.sxf.thread4;
/**
*制造数据线程
* @author sxf
*
*/
public class GiveDataThread implements Runnable {
//公共数据
private FileData fileData; //构造器
public GiveDataThread(FileData fileData) {
super();
this.fileData = fileData;
} @Override
public void run() {
//制造数据线程,造100个数据
for (int i = 0; i <10; i++) {
fileData.changeStatus("制造数据"+i);
System.out.println("【制造线程制造数据】==》制造数据"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } } }

下载数据的线程类

 package com.yeepay.sxf.thread4;
/**
* 下载线程
* @author sxf
*
*/
public class DownLoadThread implements Runnable {
private FileData fileData;
private boolean flag=true;
//构造器
public DownLoadThread(FileData fileData) {
super();
this.fileData = fileData;
} @Override
public void run() {
//开始下载线程
System.out.println("DownLoadThread.run(下载线程开始");
//根据标识
while(flag){
//进行下载
try {
fileData.execu();
} catch (TimeOutException e) {
e.printStackTrace();
flag=false;
}catch (InterruptedException e) {
// TODO: handle exception
System.out.println("DownLoadThread.run(非超时异常)");
}
} System.out.println("DownLoadThread.run(下载线程因为超时,而执行完毕)");
} }

测试类

 package com.yeepay.sxf.thread4;
/**
* 测试超时模式
* @author sxf
*
*/
public class Test2 { public static void main(String[] args) {
//声明数据类
FileData data=new FileData("sxf",true,5000);
//声明生产数据的线程
Thread giveThread=new Thread(new GiveDataThread(data));
//声明下载数据的线程
Thread downThread=new Thread(new DownLoadThread(data)); //启动线程
giveThread.start();
downThread.start();
}
}

打印结果

【制造线程制造数据】==》制造数据0
DownLoadThread.run(下载线程开始
FileData.execu(开始时间1)
顺利下载数据==>:制造数据0
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据1
顺利下载数据==>:制造数据1
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据2
顺利下载数据==>:制造数据2
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据3
顺利下载数据==>:制造数据3
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据4
顺利下载数据==>:制造数据4
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据5
顺利下载数据==>:制造数据5
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据6
顺利下载数据==>:制造数据6
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据7
顺利下载数据==>:制造数据7
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据8
顺利下载数据==>:制造数据8
FileData.execu(开始时间1)
【制造线程制造数据】==》制造数据9
顺利下载数据==>:制造数据9
FileData.execu(开始时间1)
DownLoadThread.run(下载线程因为超时,而执行完毕)
com.yeepay.sxf.thread4.TimeOutException: 已经等候5000时间了还没有数据可供下载,超时
    at com.yeepay.sxf.thread4.FileData.execu(FileData.java:42)
    at com.yeepay.sxf.thread4.DownLoadThread.run(DownLoadThread.java:24)
    at java.lang.Thread.run(Thread.java:662)

多线程程序设计学习(5)balking模式和timed模式的更多相关文章

  1. 多线程程序设计学习(3)immutable pattern模式

    Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者        1.1:immutable参与者是一个 ...

  2. 多线程程序设计学习(4)guarded suspension模式

    Guarded Suspension[生产消费者模式] 一:guarded suspension的参与者--->guardedObject(被防卫)参与者                1.1该 ...

  3. 多线程程序设计学习(9)worker pattern模式

    Worker pattern[工作模式]一:Worker pattern的参与者--->Client(委托人线程)--->Channel(通道,里边有,存放请求的队列)--->Req ...

  4. 多线程程序设计学习(2)之single threaded execution pattern

    Single Threaded Execution Pattern[独木桥模式] 一:single threaded execution pattern的参与者--->SharedResourc ...

  5. 多线程程序设计学习(6)Producer-Consumer模式

    Producer-Consumer[生产消费者模式]一:Producer-Consumer pattern的参与者--->产品(蛋糕)--->通道(传递蛋糕的桌子)--->生产者线程 ...

  6. 多线程程序设计学习(13)Active Object pattern

    Active Object[接收异步消息的对象] 一:Active Object的参与者--->客户端线程(发起某种操作请求处理)--->代理角色(工头)--->实际执行者(工人)- ...

  7. 多线程程序设计学习(12)Thread-soecific storage pattern

    Thread-Specific-Storage[线程保管箱] 一:Thread-Specific Storage的参与者--->记录日志的线程(ClientThread)--->负责获取不 ...

  8. 多线程程序设计学习(11)Two-phapse-Termination pattern

    Two-phapse-Termination[A终止B线程] 一:Two-phapse-Termination的参与者--->A线程--->B线程 二:Two-phapse-Termina ...

  9. 多线程程序设计学习(10)Future pattern

    Future pattern[订单取货模式] 一:Future pattern的参与者--->Client(客户需求)--->Host(蛋糕门店)--->Data(票据和蛋糕的接口) ...

随机推荐

  1. phonegap/cordova 启动页面

    启动phonegap应用时,因为phonegap还在加载一系列的东西,总会出现一段时间的黑屏.解决方法是设置一个启动页面(闪屏)来过渡,让应用的用户体验更好一些. 先讲ios版本的: 首先,你需要准备 ...

  2. [设计模式] 13 责任链模式 Chain of Responsibility

    转    http://blog.csdn.net/wuzhekai1985   http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...

  3. 【WCF--初入江湖】13 实战

    13 实战 在线升级 using System; using System.Collections.Generic; using System.ComponentModel; using System ...

  4. 想知道吗?CTO 比普通程序员强在哪?

    互联网的蓬勃发展,让无数的程序员身价水涨船高,都变成了「香饽饽」,更有了不少「创业」,「当上 CTO,迎娶白富美的传说」.都说不想当元帅的士兵不是好士兵,我觉得这件事见仁见智,但提升自己的价值,让自己 ...

  5. 国内最大的 Node.js 社区将 New Relic 的监控产品换成了 OneAPM

    国内最知名的 CNode 社区把 New Relic 的监控产品换成了 OneAPM .难道 APM 的老大 New Relic 已经被 OneAPM 超越? 毋庸置疑,在全球应用性能管理 SaaS ...

  6. hdu 1596 find the safest road(最短路,模版题)

    题目 这是用Dijsktra做的,稍加改动就好,1000ms..好水.. #define _CRT_SECURE_NO_WARNINGS #include<string.h> #inclu ...

  7. hdu 4676 Sum Of Gcd

    离线+分块!! 思路:序列a[1],a[2],a[3]……a[n] num[i]表示区间[L,R]中是i的倍数的个数:euler[i]表示i的欧拉函数值. 则区间的GCD之和sum=∑(C(num[i ...

  8. asp.net-(含:模拟登陆,照片列表)

    一.画好用户登录界面 同时换下请求的地址. 获取用户信息及判断代码插入位置: 一.画好用户登录界面 同时换下请求的地址. 获取用户信息及判断代码插入位置: <%@ WebHandler Lang ...

  9. 数据挖掘10大算法(1)——PageRank

    1. 前言 这系列的文章主要讲述2006年评出的数据挖掘10大算法(见图1).文章的重点将偏向于算法的来源以及算法的主要思想,不涉及具体的实现.如果发现文中有错,希望各位指出来,一起讨论. 图1 来自 ...

  10. 254. Factor Combinations

    题目: Numbers can be regarded as product of its factors. For example, 8 = 2 x 2 x 2; = 2 x 4. Write a ...