分析

介绍

  • 定期将当前数据内容写入文件中,比如文本工具的自动保存功能,定期的将数据保存到文件中。
  • 当写入的内容和上次的内容完全相同时,再向文件写入就多余了,所以就不再执行写入操作
  • 所以这个程序就是以 数据内容不同 作为守护条件,如果数据内容相同,就不执行写入操作,直接返回(balk)

作用

  • 当多个线程执行同一个操作时,如果已经执行过了,就可以不用再执行,提高程序的效率

编码实现

  • 一个线程负责写数据
  • 一个线程负责保存数据
  • 在保存数据的地方最重要需要判断:这次的修改是否已经保存
  • 如果已经保存了,就直接返回
public class Data {

    private final String filename;
    private String content;
    private boolean changed;

    public Data(String filename, String content) {
        this.filename = filename;
        this.content = content;
        this.changed = true;
    }
    //修改了数据内容
    public synchronized void change(String newContent){
        content = newContent;
        changed = true;
    }
    //若数据修改过,则保存到文件中
    public synchronized void save() throws IOException{
        if (!changed){
            //如果没有修改,就不保存了
            return;
        }
        doSave();
        changed = false;
    }
    //将数据内容保存到文件中
    public void doSave() throws IOException{
        System.out.println(Thread.currentThread().getName()+" calls doSave, content ="+content);
        Writer writer = new FileWriter(filename);
        writer.write(content);
        writer.close();
    }
}
public class ChangerThread extends Thread{

    private final Data data;
    private final Random random = new Random();

    public ChangerThread(String name,Data data) {
        super(name);
        this.data = data;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; true; i++) {
                data.change("NO."+i);//修改数据
                Thread.sleep(random.nextInt(1000));//执行其他操作
                data.save();//显示的保存,用户自己点击保存
            }
        }catch (IOException e){
            e.printStackTrace();
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}
public class SaverThread extends Thread{
    private final Data data;

    public SaverThread(String name,Data data) {
        super(name);
        this.data = data;
    }

    @Override
    public void run() {
        try {
            while (true){
                data.save();//要求保存数据
                Thread.sleep(1000);//休眠约一秒
            }
        }catch (IOException e){
            e.printStackTrace();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data("data.txt","(empty)");
        new ChangerThread("ChangeThread",data).start();
        new SaverThread("SaverThread",data).start();
    }
}

结果

Waiter calls do save,content=No.0
Waiter calls do save,content=No.1
Waiter calls do save,content=No.2
Waiter calls do save,content=No.3
Customer calls do save,content=No.4
Customer calls do save,content=No.5
Customer calls do save,content=No.6
Waiter calls do save,content=No.7
Customer calls do save,content=No.8
Waiter calls do save,content=No.9
Customer calls do save,content=No.10
Waiter calls do save,content=No.11
Customer calls do save,content=No.12
Customer calls do save,content=No.13
Waiter calls do save,content=No.14
Customer calls do save,content=No.15
Waiter calls do save,content=No.16
Waiter calls do save,content=No.17
Customer calls do save,content=No.18
Customer calls do save,content=No.19

  • 可以发现,对于每一次修改,要么用户手动保存,要么系统自动保存,不会出现保存两次的情况