多线程程序设计学习(5)balking模式和timed模式

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

数据类

 1 package com.yeepay.sxf.thread4;
 2
 3 import java.io.File;
 4 import java.io.FileOutputStream;
 5 import java.io.IOException;
 6
 7 /**
 8  * 数据类。
 9  * @author sxf
10  *
11  */
12 public class Data {
13     //文件名
14     private String fileName;
15     //文件内容
16     private String content;
17     //表示是否被修改过
18     private boolean flag;
19     //构造器
20     public Data(String fileName, String content) {
21         super();
22         this.fileName = fileName;
23         this.content = content;
24         this.flag=true;
25         File file =new File(fileName);
26         try {
27             file.createNewFile();
28             FileOutputStream iFileOutputStream=new FileOutputStream(file);
29             iFileOutputStream.write(content.getBytes());
30         } catch (IOException e) {
31             // TODO Auto-generated catch block
32             e.printStackTrace();
33         }
34     }
35     //修改内容
36     public synchronized void channgeContent(String newContent){
37         this.content=newContent ;
38         flag=true;
39     }
40
41     //把新的数据写入文件
42     private void save() throws IOException{
43         System.out.println("Data.save()"+Thread.currentThread().getName()+"执行写入操作,写入的内容为:"+content);
44         FileOutputStream fileWriter=new FileOutputStream(new File(fileName));
45         fileWriter.write(content.getBytes());
46     }
47
48     //保存内容
49     public synchronized void saveNewContent(){
50         if(!flag){
51             System.out.println("Data.saveNewContent(试图新保存,但没有更改)");
52             return;
53         }
54         try {
55             save();
56             System.out.println("Data.saveNewContent(新内容保存成功)");
57             flag=false;
58         } catch (IOException e) {
59             e.printStackTrace();
60         }
61     }
62 }

View Code

模拟修改数据的线程

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 模拟自动修改线程
 4  * @author sxf
 5  *
 6  */
 7 public class ChangeThread implements Runnable{
 8     private Data data;
 9
10     public ChangeThread(Data data) {
11         super();
12         this.data = data;
13     }
14
15     @Override
16     public void run() {
17         for(int i=0;i<20;i++){
18             //修改内容
19             System.out.println("ChangeThread.run()"+Thread.currentThread().getName()+"第"+i+"次修改");
20             data.channgeContent("新内容"+i);
21             //线程休息10秒
22             try {
23                 Thread.sleep(10000L);
24             } catch (InterruptedException e) {
25                 // TODO Auto-generated catch block
26                 e.printStackTrace();
27             }
28         }
29     }
30
31
32 }

View Code

模拟自动保存的线程

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 自动保存的线程
 4  * @author sxf
 5  *
 6  */
 7 public class ZiDongSaveThread implements Runnable{
 8     private Data data;
 9
10
11     public ZiDongSaveThread(Data data){
12         this.data=data;
13     }
14     @Override
15     public void run() {
16         while(true){
17             //保存数据
18             data.saveNewContent();
19             //线程休息1秒,意味着每隔一妙钟自动保存一次文件
20             try {
21                 Thread.sleep(1000L);
22             } catch (InterruptedException e) {
23                 // TODO Auto-generated catch block
24                 e.printStackTrace();
25             }
26         }
27
28     }
29
30 }

View Code

测试类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 测试类
 4  * @author sxf
 5  *
 6  */
 7 public class Test {
 8
 9
10 public static void main(String[] args) {
11     //声明内容
12     Data data=new Data("/usr/war/hsl.txt", "老黄买了新手机");
13     //声明自动保存线程
14     Thread saveThread=new Thread(new ZiDongSaveThread(data));
15     saveThread.setName("自动保存线程");
16     //声明模拟修改线程
17     Thread chaThread=new Thread(new ChangeThread(data));
18     chaThread.setName("模拟修改线程");
19
20     //启动线程
21     saveThread.start();
22     chaThread.start();
23
24
25 }
26 }

View Code

 打印结果

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秒钟以上,提供下载的线程没有提供数据,下载线程因超时异常,停止下载线程运行。

超时异常类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 超时异常类
 4  * @author sxf
 5  *
 6  */
 7 public class TimeOutException extends InterruptedException {
 8
 9     public TimeOutException(String msg){
10         super(msg);
11     }
12 }

View Code

下载数据的数据类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 下载数据类
 4  * @author sxf
 5  *
 6  */
 7 public class FileData {
 8     //提供下载的数据
 9     private String data;
10     //有数据可下载
11     private boolean flag;
12     //超时时间
13     private long timeout;
14
15     //构造器
16     public FileData(String data, boolean flag, long timeout) {
17         super();
18         this.data = data;
19         this.flag = flag;
20         this.timeout = timeout;
21     }
22
23
24     //修改状态,唤醒其他所有线程
25     public synchronized void  changeStatus(String data){
26         this.data=data;
27         flag=true;
28         notify();
29     }
30
31     //下载操作。如果等timeout/1000秒钟,没有数据供下载,就报超时异常,终止下载
32     public synchronized void execu() throws InterruptedException{
33         //开始执行的时间
34         long start=System.currentTimeMillis();
35         int i=0;
36         System.out.println("FileData.execu(开始时间1)");
37         while (!flag) {
38             //现在的时间
39             long now=System.currentTimeMillis();
40             long reset=timeout-(now-start);
41             if(reset<=0){
42                 throw new TimeOutException("已经等候"+timeout+"时间了还没有数据可供下载,超时");
43             }
44             //如果没有超时,就让下载线程进入wait set,设置超时时间。被唤醒,继续从这里开始执行。
45             wait(reset);
46         }
47         //真正的下载操作
48         download();
49     }
50
51
52     //真正的下载操作
53     private void download(){
54         System.out.println("顺利下载数据==>:"+data);
55         //下载完之后,将下载状态改为不可下载,等待放入新数据供下载
56         this.flag=false;
57     }
58
59     public String getData() {
60         return data;
61     }
62     public void setData(String data) {
63         this.data = data;
64     }
65     public boolean isFlag() {
66         return flag;
67     }
68     public void setFlag(boolean flag) {
69         this.flag = flag;
70     }
71
72
73
74     public long getTimeout() {
75         return timeout;
76     }
77     public void setTimeout(long timeout) {
78         this.timeout = timeout;
79     }
80 }

View Code

提供数据供下载的线程类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  *制造数据线程
 4  * @author sxf
 5  *
 6  */
 7 public class GiveDataThread implements Runnable {
 8     //公共数据
 9     private FileData fileData;
10
11     //构造器
12     public GiveDataThread(FileData fileData) {
13         super();
14         this.fileData = fileData;
15     }
16
17
18
19     @Override
20     public void run() {
21             //制造数据线程,造100个数据
22             for (int i = 0; i <10; i++) {
23                 fileData.changeStatus("制造数据"+i);
24                 System.out.println("【制造线程制造数据】==》制造数据"+i);
25                 try {
26                     Thread.sleep(1000);
27                 } catch (InterruptedException e) {
28                     // TODO Auto-generated catch block
29                     e.printStackTrace();
30                 }
31
32         }
33
34     }
35
36
37 }

View Code

下载数据的线程类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 下载线程
 4  * @author sxf
 5  *
 6  */
 7 public class DownLoadThread implements Runnable {
 8     private FileData fileData;
 9     private boolean flag=true;
10     //构造器
11     public DownLoadThread(FileData fileData) {
12         super();
13         this.fileData = fileData;
14     }
15
16     @Override
17     public void run() {
18         //开始下载线程
19         System.out.println("DownLoadThread.run(下载线程开始");
20         //根据标识
21         while(flag){
22             //进行下载
23             try {
24                 fileData.execu();
25             } catch (TimeOutException e) {
26                 e.printStackTrace();
27                 flag=false;
28             }catch (InterruptedException e) {
29                 // TODO: handle exception
30                 System.out.println("DownLoadThread.run(非超时异常)");
31             }
32         }
33
34         System.out.println("DownLoadThread.run(下载线程因为超时,而执行完毕)");
35     }
36
37
38
39
40
41 }

View Code

测试类

 1 package com.yeepay.sxf.thread4;
 2 /**
 3  * 测试超时模式
 4  * @author sxf
 5  *
 6  */
 7 public class Test2 {
 8
 9
10     public static void main(String[] args) {
11         //声明数据类
12         FileData data=new FileData("sxf",true,5000);
13         //声明生产数据的线程
14         Thread giveThread=new Thread(new GiveDataThread(data));
15         //声明下载数据的线程
16         Thread downThread=new Thread(new DownLoadThread(data));
17
18         //启动线程
19         giveThread.start();
20         downThread.start();
21     }
22 }

View Code

打印结果

【制造线程制造数据】==》制造数据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)

 

时间: 2024-09-25 07:40:58

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

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

Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者        1.1:immutable参与者是一个字段的值都无法更改的类.        1.2:immutable也没有任何用来更改字段值的方法.        1.3:immutable参与者方法不需要设置synchronized 二:immutable pattern模式什么时候使用--->当实例产生后,状态不再变化时        2.1实例状

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

Guarded Suspension[生产消费者模式] 一:guarded suspension的参与者--->guardedObject(被防卫)参与者                1.1该参与者拥有一个被防卫的方法(getRequest),如果警戒条件达成,则执行.警戒条件不达成,则线程进入wait set                1.2该参与者还拥有一个改变参与者状态的方法(putRequest).参与者的状态影响着警戒条件的是否达成. --->该模式的角色:生产端线程,消费端线

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

Worker pattern[工作模式]一:Worker pattern的参与者--->Client(委托人线程)--->Channel(通道,里边有,存放请求的队列)--->Request(工作内容的包装)--->Worker(工人线程)        二:Worker pattern模式什么时候使用--->类似生产者消费者 三:Worker pattern思考 四进阶说明--->工作线程取出请求内容包装后,根据多态,不同的请求执行不同的业务方法   Request接

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

Single Threaded Execution Pattern[独木桥模式] 一:single threaded execution pattern的参与者--->SharedResource(共享资源) 二:single threaded execution pattern模式什么时候使用--->多线程程序设计时--->数据可被多个线程访问的时候--->共享资源状态可能变化的时候--->需要确保数据安全性的时候 三:single threaded execution p

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

Producer-Consumer[生产消费者模式]一:Producer-Consumer pattern的参与者--->产品(蛋糕)--->通道(传递蛋糕的桌子)--->生产者线程(制造蛋糕的线程)--->消费者线程(吃掉蛋糕的线程)         二:Producer-Consumer pattern模式什么时候使用--->大量生产+大量消费的模式 三:Producer-Consumer pattern思考--->[生产消费者模式],肩负保护数据安全性使命的是通道

多线程程序设计学习(7)read-write lock pattern

Read-Write Lock Pattern[读写]一:Read-Write Lock Pattern的参与者--->读写锁--->数据(共享资源)--->读线程--->写线程         二Read-Write Lock Pattern模式什么时候使用---> * 为了多线线程环境下保护数据安全,我们必须避免的冲突 * 一个线程读取,另一个线程写入的read-write conflick * 一个线程写入,另一个线程写入的write-write conflick *

多线程程序设计学习(8)Thread-Per-Message

Thread-Per-Message[这个工作交给你模式]一:Thread-Per-Message的参与者--->Client(委托人)--->host(中介开线程)--->hepler(真正工作的工人)        二:Thread-Per-Message模式什么时候使用--->提升响应时间,降低延迟时间--->适合在操作顺序无所谓的时候--->(委托人)不需要返回值的时候--->应用在服务器的制作(我提供原材料,你加工,我不关心结果)--->调用方法+

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

Future pattern[订单取货模式] 一:Future pattern的参与者--->Client(客户需求)--->Host(蛋糕门店)--->Data(票据和蛋糕的接口)--->Future(蛋糕票据)--->ReaData(制作蛋糕过程)        二:Future pattern模式什么时候使用---> 三:Future pattern思考       ---> 四进阶说明        ---> 数据类接口 1 package com.

多线程程序设计学习(1)之多线程程序的评量标准

多线程程序的评量标准--->安全性[不损坏对象]        (1)不损坏对象是一种比喻手法,就是数据的一致性.比如银行的扣款操作,并发扣款,账户不会出现负数的余额.--->生存性[进行必要的处理]        (1)指也许不是现在,但一定会进行的必要处理.好比异常处理机制.在出现多线死锁等情况下的必要处理.--->复用性        (1)指可再利用的类,这不是必要条件,但却是体现程序质量重点条件.封装的意思.        (2)如果A类是一个已经确定可正常使用的软件程序的一部