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. codeforces 397B

    #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #includ ...

  2. mysql 常用操作

    添加用户并设置权限: grant all on *.* to root@‘%’ identified by ‘123456’with grant option; all:所有权限 select,ins ...

  3. First Lua function running in C

    这是我在C里面跑出来的第一个Lua 文件, 纪念一下. 1.Set up envirnonment: Mac下面 Lua的src (即include) 和lib(binary)是分开的, 所以需要分别 ...

  4. 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)

    比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子.   ...

  5. ios 沙盒 NSCoding(相当于JAVA对象序列化) 归档 数据存储

    通过NSCoding能实现像JAVA一样能够实现对象的序列化,可以保存对象到文件里. NSCoding 跟其他存储方式略有不同,他可以存储对象 对象存储的条件是: 对象需要遵守 NSCoding 协议 ...

  6. 转一篇:文档笔记之Django QuerySet

    这个放着,说不定以后作一些更深入的查询时,用得着的. http://www.rapospectre.com/blog/7/ 今天刚刚答完辩体完检就跑来更新博客了!!! 先补上第一篇: 一般情况下,我们 ...

  7. 阻止事件冒泡(stopPropagation和cancelBubble)和阻止默认行为(preventDefault和returnValue)

    <div id="divId1" style="width:500px;height:500px;background-color:#3ac;text-align: ...

  8. 李洪强iOS开发之OC语言构造方法

    OC语言构造方法 一.构造方法 (一)构造方法的调用 完整的创建一个可用的对象:Person *p=[Person new]; New方法的内部会分别调用两个方法来完成2件事情,1)使用alloc方法 ...

  9. iOS开发--_weak typeof(self) weakSelf = self

    _weak typeof(self) weakSelf = self;  (一)内存管理原则  1.默认strong,可选weak.strong下不管成员变量还是property,每次使用指针指向一个 ...

  10. python 时间处理(time和datetime介绍)

    python的有关时间的有哪几种呢?今天我们介绍两个:time和datetime time模块提供各种操作时间的函数 datetime模块定义了下面这几个类: datetime.date:表示日期的类 ...