今日内容介绍
1、多线程安全问题
2、等待唤醒机制

01线程操作共享数据的安全问题

  *A:线程操作共享数据的安全问题如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

02售票的案例

*A:售票的案例

 /** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现类对象 Tickets t = new Tickets(); //创建3个Thread类对象,传递Runnable接口实现类 Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } } public class Tickets implements Runnable{ //定义出售的票源 private int ticket = 100; private Object obj = new Object(); public void run(){ while(true){ if( ticket > 0){ System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--); } } } }

03线程安全问题引发

*A:线程安全问题引发

/** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/
public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现类对象 Tickets t = new Tickets(); //创建3个Thread类对象,传递Runnable接口实现类 Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } } /* * 通过线程休眠,出现安全问题 */ public class Tickets implements Runnable{ //定义出售的票源 private int ticket = 100; private Object obj = new Object(); public void run(){ while(true){ //对票数判断,大于0,可以出售,变量--操作 if( ticket > 0){ try{ Thread.sleep(10); //加了休眠让其他线程有执行机会 }catch(Exception ex){} System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--); } } } }

04同步代码块解决线程安全问题

*A:同步代码块解决线程安全问题

  *A:售票的案例/** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现类对象 Tickets t = new Tickets(); //创建3个Thread类对象,传递Runnable接口实现类 Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } } /* * 通过线程休眠,出现安全问题 * 解决安全问题,Java程序,提供技术,同步技术 * 公式: * synchronized(任意对象){ * 线程要操作的共享数据 * } * 同步代码块 */ public class Tickets implements Runnable{ //定义出售的票源 private int ticket = 100; private Object obj = new Object(); public void run(){ while(true){ //线程共享数据,保证安全,加入同步代码块 synchronized(obj){ //对票数判断,大于0,可以出售,变量--操作 if( ticket > 0){ try{ Thread.sleep(10); }catch(Exception ex){} System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--); } } } } }

05同步代码块的执行原理

   A:同步代码块的执行原理同步代码块: 在代码块声明上 加上synchronizedsynchronized (锁对象) {可能会产生线程安全问题的代码}同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

06同步的上厕所原理

  *A:同步的上厕所原理a:不使用同步:线程在执行的过程中会被打扰线程比喻成人线程执行代码就是上一个厕所第一个人正在上厕所,上到一半,被另外一个人拉出来b:使用同步:线程比喻成人线程执行代码就是上一个厕所锁比喻成厕所门第一个人上厕所,会锁门第二个人上厕所,看到门锁上了,等待第一个人上完再去上厕所

07同步方法

  *A:同步方法:/** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现类对象 Tickets t = new Tickets(); //创建3个Thread类对象,传递Runnable接口实现类 Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } } *A:同步方法 /* * 采用同步方法形式,解决线程的安全问题 * 好处: 代码简洁 * 将线程共享数据,和同步,抽取到一个方法中 * 在方法的声明上,加入同步关键字 * * 问题: * 同步方法有锁吗,肯定有,同步方法中的对象锁,是本类对象引用 this * 如果方法是静态的呢,同步有锁吗,绝对不是this * 锁是本类自己.class 属性 * 静态方法,同步锁,是本类类名.class属性 */ public class Tickets implements Runnable{ //定义出售的票源 private int ticket = 100; public void run(){ while(true){ payTicket(); } } public synchronized void payTicket(){ if( ticket > 0){ try{ Thread.sleep(10); }catch(Exception ex){} System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--); } } }

08JDK1.5新特性Lock接口

   *A:JDK1.5新特性Lock接口查阅API,查阅Lock接口描述,Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。 Lock接口中的常用方法void lock()void unlock() Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能。 我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Ticket

09Lock接口改进售票案例

   *A:Lock接口改进售票案例/** 多线程并发访问同一个数据资源* 3个线程,对一个票资源,出售*/public class ThreadDemo {public static void main(String[] args) { //创建Runnable接口实现类对象 Tickets t = new Tickets(); //创建3个Thread类对象,传递Runnable接口实现类 Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } } /* * 使用JDK1.5 的接口Lock,替换同步代码块,实现线程的安全性 * Lock接口方法: * lock() 获取锁 * unlock()释放锁 * 实现类ReentrantLock */ public class Tickets implements Runnable{ //定义出售的票源 private int ticket = 100; //在类的成员位置,创建Lock接口的实现类对象 private Lock lock = new ReentrantLock(); public void run(){ while(true){ //调用Lock接口方法lock获取锁 lock.lock(); //对票数判断,大于0,可以出售,变量--操作 if( ticket > 0){ try{ Thread.sleep(10); System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--); }catch(Exception ex){ }finally{ //释放锁,调用Lock接口方法unlock lock.unlock(); } } } } }

10线程的死锁原理

   *A:线程的死锁原理  当线程任务中出现了多个同步(多个锁)  时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就 避免掉。synchronzied(A锁){synchronized(B锁){}}

11线程的死锁代码实现

   *A:线程的死锁代码实现public class DeadLock implements Runnable{ private int i = 0; public void run(){ while(true){ if(i%2==0){ //先进入A同步,再进入B同步 synchronized(LockA.locka){ System.out.println("if...locka"); synchronized(LockB.lockb){ System.out.println("if...lockb"); } } }else{ //先进入B同步,再进入A同步 synchronized(LockB.lockb){ System.out.println("else...lockb"); synchronized(LockA.locka){ System.out.println("else...locka"); } } } i++; } } } public class DeadLockDemo { public static void main(String[] args) { DeadLock dead = new DeadLock(); Thread t0 = new Thread(dead); Thread t1 = new Thread(dead); t0.start(); t1.start(); } } public class LockA { private LockA(){} public static final LockA locka = new LockA(); } public class LockB { private LockB(){} public static final LockB lockb = new LockB(); }

### 12线程等待与唤醒案例介绍

   *A:线程等待与唤醒案例介绍 等待唤醒机制所涉及到的方法:  wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。  notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。  notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。其实,所谓唤醒的意思就是让 线程池中的线程具备执行资格。必须注意的是,这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

13线程等待与唤醒案例资源类编写

  *A:线程等待与唤醒案例资源类编写/**  定义资源类,有2个成员变量*  name,sex*  同时有2个线程,对资源中的变量操作*  1个对name,age赋值*  2个对name,age做变量的输出打印*/public class Resource { public String name; public String sex; }

14线程等待与唤醒案例输入和输出线程

   A:线程等待与唤醒案例输入和输出线程/**  输入的线程,对资源对象Resource中成员变量赋值*  一次赋值 张三,男*  下一次赋值 lisi,nv*/public class Input implements Runnable { private Resource r=new Resource(); public void run() { int i=0; while(true){ if(i%2==0){ r.name="张三"; r.sex="男"; }else{ r.name="lisi"; r.sex="女"; } i++; } } } /* * 输出线程,对资源对象Resource中成员变量,输出值 */ public class Output implements Runnable { private Resource r=new Resource() ; public void run() { while(true){ System.out.println(r.name+"..."+r.sex); } } }

15线程等待与唤醒案例测试类

   A:线程等待与唤醒案例测试类/**  开启输入线程和输出线程,实现赋值和打印值*/public class ThreadDemo{public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(); Output out = new Output(); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }

16线程等待与唤醒案例null值解决

   A:线程等待与唤醒案例null值解决/**  输入的线程,对资源对象Resource中成员变量赋值*  一次赋值 张三,男*  下一次赋值 lisi,nv*/public class Input implements Runnable { private Resource r; public Input(Resource r){ this.r=r; } public void run() { int i=0; while(true){ if(i%2==0){ r.name="张三"; r.sex="男"; }else{ r.name="lisi" r.sex="女" } i++; } } } /* * 输出线程,对资源对象Resource中成员变量,输出值 */ public class Output implements Runnable { private Resource r; public Output(Resource r){ this.r=r; } public void run() { while(true){ System.out.println(r.name+"..."+r.sex); } } } } /* * 开启输入线程和输出线程,实现赋值和打印值 */ public class ThreadDemo{ public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }

17线程等待与唤醒案例数据安全解决

A:线程等待与唤醒案例数据安全解决/**  输入的线程,对资源对象Resource中成员变量赋值*  一次赋值 张三,男*  下一次赋值 lisi,nv*/public class Input implements Runnable { private Resource r; public Input(Resource r){ this.r=r; } public void run() { int i=0; while(true){ synchronized(r){ if(i%2==0){ r.name="张三"; r.sex="男"; }else{ r.name="lisi" r.sex="女" } i++; } } } /* * 输出线程,对资源对象Resource中成员变量,输出值 */ public class Output implements Runnable { private Resource r; public Output(Resource r){ this.r=r; } public void run() { while(true){ synchronized(r){ System.out.println(r.name+"..."+r.sex); } } } } } /* * 开启输入线程和输出线程,实现赋值和打印值 */ public class ThreadDemo{ public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }

18线程等待与唤醒案例通信的分析

*A:线程等待与唤醒案例通信的分析输入:赋值后,执行方法wait()永远等待输出:变量值打印输出,在输出等待之前,唤醒输入的notify(),自己在wait()永远等待输入:被唤醒后,重新对变量赋值,赋值后,必须唤醒输出的线程notify(),自己的wait()

19线程等待与唤醒案例的实现

*A 线程等待与唤醒案例的实现/**  定义资源类,有2个成员变量*  name,sex*  同时有2个线程,对资源中的变量操作*  1个对name,age赋值*  2个对name,age做变量的输出打印*/public class Resource { public String name; public String sex; public boolean flag = false; } /* * 输入的线程,对资源对象Resource中成员变量赋值 * 一次赋值 张三,男 * 下一次赋值 lisi,nv */ public class Input implements Runnable { private Resource r ; public Input(Resource r){ this.r = r; } public void run() { int i = 0 ; while(true){ synchronized(r){ //标记是true,等待 if(r.flag){ try{r.wait();}catch(Exception ex){} } if(i%2==0){ r.name = "张三"; r.sex = "男"; }else{ r.name = "lisi"; r.sex = "nv"; } //将对方线程唤醒,标记改为true r.flag = true; r.notify(); } i++; } } } /* * 输出线程,对资源对象Resource中成员变量,输出值 */ public class Output implements Runnable { private Resource r ; public Output(Resource r){ this.r = r; } public void run() { while(true){ synchronized(r){ //判断标记,是false,等待 if(!r.flag){ try{r.wait();}catch(Exception ex){} } System.out.println(r.name+".."+r.sex); //标记改成false,唤醒对方线程 r.flag = false; r.notify(); } } } } /* * 开启输入线程和输出线程,实现赋值和打印值 */ public class ThreadDemo{ public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }

作业测试

1、wait和sleep的区别
2、线程的生命周期(五中状态的切换流程)
3、有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池用一个数组int[] arr = {10,5,20,50,100,200,500,800,2,80,300};
创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”,随机从arr数组中获取奖项元素并打印在控制台上,格式如下:

抽奖箱1 又产生了一个 10 元大奖
抽奖箱2 又产生了一个 100 元大奖
//.....

4、某公司组织年会,会议入场时有两个入口,在入场时每位员工都能获取一张双色球彩票,假设公司有100个员工,利用多线程模拟年会入场过程,

并分别统计每个入口入场的人数,以及每个员工拿到的彩票的号码。线程运行后打印格式如下:
编号为: 2 的员工 从后门 入场! 拿到的双色球彩票号码是: [17, 24, 29, 30, 31, 32, 07]
编号为: 1 的员工 从后门 入场! 拿到的双色球彩票号码是: [06, 11, 14, 22, 29, 32, 15]
//.....
从后门入场的员工总共: 13 位员工
从前门入场的员工总共: 87 位员工

转载于:https://www.cnblogs.com/zoick/p/10615437.html

27_多线程_第27天(线程安全、线程同步、等待唤醒机制、单例设计模式)相关推荐

  1. 27_多线程_第27天(线程安全、线程同步、等待唤醒机制、单例设计模式)_讲义...

    今日内容介绍 1.多线程安全问题 2.等待唤醒机制 01线程操作共享数据的安全问题 *A:线程操作共享数据的安全问题如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程 ...

  2. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  3. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

    一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...

  4. 进阶12 多线程、等待唤醒机制、线程池

    多线程 我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计? 要解决上述问题,咱们得使用多进程或者多线程来解决. 并发与并行 并发:指 ...

  5. java基础提升(二):多线程、线程安全、线程状态、等待唤醒机制、线程池

    目录 一. 多线程 1.1并发与并行 1.2 线程与进程 1.3 创建线程类 1.3.1 方式一:继承Thread类 1.3.2 方式二:实现Runnable接口 1.3.3 Thread和Runna ...

  6. 24.多线程(等待唤醒机制,volatile,CAS 算法,线程池,定时器,设计模式)

    1.线程间的等待唤醒机制 Object 类中   void wait ()  在其他线程调用此对象的 notify () 方法或 notifyAll () 方法前,导致当前线程等待.         ...

  7. 单例设计模式八种方式——5) 懒汉式(线程安全,同步代码块) 6) 双重检查 7) 静态内部类 8) 枚举

    懒汉式(线程安全,同步代码块)应用实例 优缺点说明: 1) 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低, 改为同步产生实例化的的代码块 2) 但是这种同步并不能起到线程同步的作 ...

  8. 单例设计模式介绍||单例设计模式八种方式——1) 饿汉式(静态常量) 2) 饿汉式(静态代码块) 3) 懒汉式(线程不安全) 4) 懒汉式(线程安全,同步方法)

    单例模式 单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). 比如Hibernate的 ...

  9. 主线程 唤醒_Java等待唤醒机制统计子线程运行时间的方式及其疑问

    我想在主线程中获取子线程运行的时间,一种方式是使用join()方法,经验证是可行的: 但是我想试试等待唤醒机制,思路是:子线程启动后主线程等待,子线程结束后唤醒主线程,但是不太清楚为什么会报错,从运行 ...

最新文章

  1. Linux redhat 5.4上安装MYDNS
  2. hdu 4309 最大流 + DFS
  3. linux用绝对路径执行mysql命令_Linux 相对路径和绝对路径的使用
  4. 青岛农业大学第九届ACM程序设计竞赛
  5. 计算机网络(谢希仁第八版)第二章:物理层
  6. 感知机中任一点到超平面的距离的公式推导
  7. POJ - 3254 Corn Fields(状压dp)
  8. 有效的Java第三版有哪些新功能?
  9. 查看目标主机安装的杀毒软件
  10. 屠呦呦入选《时代周刊》100位最具影响力女性人物榜
  11. 多线程,多进程使用场景
  12. 掌握到胃-奈氏图与伯德图的绘制
  13. 等额本金等额本息推导
  14. windows 系统遍历USB设备 VID和PID
  15. 史上最全零基础学习java干货!千万别错过!
  16. php解压有密码的zip,linux下解压有密码的rar压缩包的方法
  17. 大众点评数据分析报告
  18. 跟着团子学SAP SD:项目里程碑开票流程演示(含预收账款“开票”及正式开票) VF01
  19. Java常用设计模式(三)
  20. 如何在debian上安装google pingyin

热门文章

  1. hive和hadoop关系
  2. VB 单击ListView控件某列表头进行排序
  3. 技术分析在于少而精,多则惑
  4. 贺建奎给自己做了三次“基因编辑”:想当中国爱因斯坦,却变成生物狂人
  5. 不造AI杀人武器当然好,但牛津学者觉得马斯克们忽略了重点
  6. 全球AI芯片企业排行:英伟达第1,华为第12(七家中国公司入围Top24)
  7. 前阿里P10大神AI创业,主打决策智能,从《星际争霸II》开始
  8. Linux命令参数详细解析 mv
  9. 将 Exchange 2003 移动到新计算机并保持相同的服务器名
  10. Angular4的QuickStart—— ES6 而非TypeScript