一、任务

创建20个线程,其中10个线程是将数据备份到 A 数据库中,另外10 个线程将数据备份到 B 数据库中,并且备份 A 数据库和 备份 B 数据库的是交叉运行的。

二、实现

1、实现备份 A 数据库和备份 B 数据库的 task。

/**
* Description: 当flag=true的时候备份 A 数据库
* 当flag=false的时候备份 B数据库 以此实现交叉备份
*/
public class TaskBackup
{
volatile private boolean flag=false;// 采用volatile关键字,使变量于多个线程之间可见 synchronized public void backupA(){ //synchronized 关键字,避免多个线程对同一对象的修改,导致“脏读”
try {
//记住,这里的判断一定要用while 而不是用if,为什么呢?因为存在多个线程,不止备份B数据库的线程在等待,可能备份A数据库的线程也在等待,如果用if
//可能会导致 同类唤醒同类的 情况导致线程的“假死”。
while (flag==false){
this.wait();
}
System.out.println(Thread.currentThread().getName()+"正在备份 A 数据库!");//模拟备份数据库
flag=false;
this.notifyAll();//唤醒所有等待的线程,当然这里并不会唤醒backupA 的线程,原因在于,backupA的线程这个时候又做了一个while判断,导致线程继续在等待了,而只有backupB的线程被唤醒了
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public void backupB(){
try {
while (flag==true){
this.wait();
}
System.out.println(Thread.currentThread().getName()+"正在备份 B 数据库!");//模拟备份数据库
            flag=true; 
this.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

2、分别创建线程执行 备份任务

public class ThreadBackupA extends Thread
{
private TaskBackup taskPackup; public ThreadBackupA(TaskBackup taskPackup)
{
this.taskPackup = taskPackup;
} @Override
public void run()
{
super.run();
taskPackup.backupA();
}
}
public class ThreadBackupB extends Thread
{
private TaskBackup taskPackup; public ThreadBackupB(TaskBackup taskPackup)
{
this.taskPackup = taskPackup;
} @Override
public void run()
{
super.run();
taskPackup.backupB();
}
}

3、执行任务查看结果

public class Run
{
public static void main(String[] args)
{
TaskBackup taskPackup=new TaskBackup();
for (int i=0;i<20;i++){
ThreadBackupA threadBackupA=new ThreadBackupA(taskPackup);
ThreadBackupB threadBackupB=new ThreadBackupB(taskPackup);
threadBackupA.start();
threadBackupB.start();
}
}
}

三、结语

觉得这个例子写得特别棒,所以特地记录了一下。它把 诸如 线程notify过程中 wait条件发生改变、同类唤醒同类导致的“假死”问题 等,都做了一个很好的概括应用和解决。笔主资历尚浅,说的不好的地方,还请不吝指教,谢谢!

wait/notify 实现多线程交叉备份的更多相关文章

  1. 《Java多线程编程核心技术》知识梳理

    <Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...

  2. MySQL多线程备份工具mydumper

    mydumper是一个针对MySQL和Drizzle的高性能多线程的备份和恢复工具.此工具的开发人员分别来自MySQL.Fackbook.SkySQL公司,目前已经有一些大型产品业务测试并使用了该工具 ...

  3. java多线程编程核心技术——第三章

    第一节等待/通知机制 1.1不使用等待/通知机制实现线程间的通讯 1.2什么是等待/通知机制 1.3等待/通知机制的实现 1.4方法wait()锁释放与notify()锁不释放 1.5当interru ...

  4. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  5. java多线程编程核心技术——第三章总结

    第一节等待/通知机制 1.1不使用等待/通知机制实现线程间的通讯 1.2什么是等待/通知机制 1.3等待/通知机制的实现 1.4方法wait()锁释放与notify()锁不释放 1.5当interru ...

  6. 《JAVA多线程编程核心技术》 笔记:第三章:线程间通信

    一. 等待/通知机制:wait()和notify()1.1.使用的原因:1.2 具体实现:wait()和notify()1.2.1 方法wait():1.2.2 方法notify():1.2.3 wa ...

  7. 《Java多线程编程核心技术》读后感(十)

    一生产一消费:操作栈 本实例是使生产者向堆栈List对象中放入数据,使消费者从List堆栈中取出数据.List最大容量是1 package Third; import java.util.ArrayL ...

  8. Java多线程编程(三)线程间通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  9. Java多线程编程核心技术-第3章-线程间通信-读书笔记

    第 3 章 线程间通信 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大 ...

随机推荐

  1. 最耗性能的SQL语句

    设计优化–常见杀手级SQL •SELECT * vsSELECT col1, col2 •ORDER BY RAND() •LIMIT huge_num, offset •SELECT COUNT(* ...

  2. Less的@import指令

    Less的@import指令 Less中,可以通过 @import指令来导入外部文件.@import指令可以放在代码中的任何位置,导入文件时的处理方式取决于文件的扩展名: 如果扩展名是 .css,文件 ...

  3. 11-散列4 Hashing - Hard Version

    题目 Sample Input: 11 33 1 13 12 34 38 27 22 32 -1 21 Sample Output: 1 13 12 21 33 34 38 27 22 32 基本思路 ...

  4. B2B电商系统开发建设的价格费用取决于哪些要素

    B2B电子商务系统平台建设开发怎么做?如何搭建一个电商系统网站平台?相信我们的企业商家在搭建电子商务系统的时候都会进行前期的系统策划,但是对于电子商务系统的构建绝大多数人都有一个误区,那就是对于电子商 ...

  5. MySql基础入门-mysql的结构层次

    了解MySql必须牢牢记住其体系结构图,Mysql是由SQL接口,解析器,优化器,缓存,存储引擎组成的. 1.Connectors指的是不同语言中与SQL的交互 2.Management Servei ...

  6. P1156 垃圾陷阱

    题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2<=D<=100)英尺. 卡门想把垃圾堆起来,等到 ...

  7. Dubbo源码学习--服务发布(ProxyFactory、Invoker)

    上文分析了Dubbo服务发布的整体流程,但服务代理生成的具体细节介绍得还不是很详细.下面将会接着上文继续分析.上文介绍了服务代理生成的切入点,如下: Invoker<?> invoker ...

  8. Scala中的override

    Scala中的override override是覆盖的意思,在很多语言中都有,在scala中,override是非常常见的,在类继承方面,它和java不一样,不是可写可不写的了,而是必须写的.如果不 ...

  9. 对于vue.js初步了解

    由于本人做的是javaWeb的开发,对于前端的了解还是有限,今天对于vue.js了解了下(主要是看官方api),把自己的心得说一下,希望各位大神可以补充,谢谢   http://www.runoob. ...

  10. MySQL数据库数据信息迁移

    环境内核信息: [root@zabbix-01 ~]# uname -a Linux lodboyedu-01 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21 19:2 ...