多线程学习之四返回模式
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.benxq.thread5; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * Created by qucf on 2015年10月22日. */ public class Data { //文件名 private String fileName; //文件内容 private String content; //标示是否被修改 private boolean flag; //构造器 public Data(String fileName,String content){ this.fileName=fileName; this.content=content; this.flag=true; File file=new File(fileName); try { file.createNewFile(); FileOutputStream out=new FileOutputStream(file); out.write(content.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //修改内容 public synchronized void updateContent(String content){ this.content=content; flag=true; } //把新内容写入文件 public void save(){ System.out.println("线程"+Thread.currentThread().getName()+"执行保存,保存内容为"+content); try { FileOutputStream out=new FileOutputStream(new File(fileName)); out.write(content.getBytes()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //保存内容 public synchronized void saveNewContent(){ if(!flag){ System.out.println("线程"+Thread.currentThread().getName()+"试图保存,但内容没有更改"); return; } save(); System.out.println("线程"+Thread.currentThread().getName()+"保存内容成功"); flag=false; } }
修改内容线程
/** * */ package com.benxq.thread5; /** * Created by qucf on 2015年10月22日. */ public class ChangeThread implements Runnable{ private Data data; public ChangeThread(Data data) { this.data=data; } @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("线程:"+Thread.currentThread().getName()+"第"+i+"次修改"); data.updateContent("新内容"+i); //让线程休息10秒 try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
自动保存线程
/** * */ package com.benxq.thread5; /** * 模拟保存线程 * Created by qucf on 2015年10月22日. */ public class SaveThread implements Runnable{ private Data data; public SaveThread(Data data){ this.data=data; } @Override public void run() { while(true){ data.saveNewContent(); //线程休息1秒 try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
主线程
/** * */ package com.benxq.thread5; /** * Created by qucf on 2015年10月22日. */ public class Test { public static void main(String[] args) { Data data=new Data("D://thread.txt", "aaa"); //修改线程 Thread ut=new Thread(new ChangeThread(data)); ut.start(); //保存线程 Thread save=new Thread(new SaveThread(data)); save.start(); } }