wait/notify 实现多线程交叉备份
时间:2022-05-04
本文章向大家介绍wait/notify 实现多线程交叉备份,主要内容包括一、任务、二、实现、三、结语、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
一、任务
创建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 数据库!");//模拟备份数据库
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条件发生改变、同类唤醒同类导致的“假死”问题 等,都做了一个很好的概括应用和解决。笔主资历尚浅,说的不好的地方,还请不吝指教,谢谢!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android底部弹窗的实现示例代码
- Android编程实现自定义渐变颜色效果详解
- ES11屡试不爽的新特性,你用上了几个?
- Android设计模式之策略模式详解
- Android实现类似iOS风格的对话框实例代码
- Android 给图片加上水印的示例代码(支持logo+文字)
- Android studio 下JNI编程实例并生成so库的实现代码
- Android实现简单时钟View的方法
- Android编程之创建自己的内容提供器实现方法
- Android自定义View圆形和拖动圆、跟随手指拖动效果
- Android开发之OkHttpUtils的具体使用方法
- Xshell5连接虚拟机中的Linux的方法以及失败原因解决
- Android 多线程的实现方法总结
- Android编程之SQLite数据库操作方法详解
- 浅谈android组件化之ARouter简单使用