首页 > 代码库 > 线程(while 和 if 剖析)
线程(while 和 if 剖析)
那存钱取钱为例:
要求实现一次存一次取的操作 不可出现连续存或连续取;
如果只有存钱和取钱各自只有一个线程在操作使用 if 的话可以满足要求:
1 package com.thread; 2 /** 3 * 模拟同步取款的问题 4 * @author dr 5 * 6 */ 7 public class ThreadTest { 8 public static void main(String[] args) { 9 final Account account = new Account();10 //取出20011 new Thread(new Runnable() {12 @Override13 public void run() {14 for(int i=0;i<3;i++){15 try {16 Thread.sleep(500);17 } catch (InterruptedException e) {18 // TODO Auto-generated catch block19 e.printStackTrace();20 }21 account.getMoney(200);22 }23 }24 }).start();25 //存入30026 new Thread(new Runnable() {27 @Override28 public void run() {29 for(int i=0;i<3;i++){30 try {31 Thread.sleep(500);32 } catch (InterruptedException e) {33 // TODO Auto-generated catch block34 e.printStackTrace();35 }36 account.setMoney(300);37 }38 }39 }).start();40 }41 }42 class Account {43 44 private int balance = 1000;45 private boolean setMoney = true;46 public synchronized void getMoney(int count){47 if(setMoney){48 try {49 this.wait();50 } catch (InterruptedException e) {51 // TODO Auto-generated catch block52 e.printStackTrace();53 }54 }55 int result =balance - count;56 if(result >= 0){57 balance = result;58 System.out.println(Thread.currentThread().getName()+"取出:"+count+"元,剩余:"+balance);59 }else{60 System.out.println("余额不足...");61 }62 setMoney = true;63 this.notify();64 }65 public synchronized void setMoney(int count){66 if(!setMoney){67 try {68 this.wait();69 } catch (InterruptedException e) {70 // TODO Auto-generated catch block71 e.printStackTrace();72 }73 }74 balance += count;75 System.out.println(Thread.currentThread().getName()+"存入:"+count+"元,剩余:"+balance);76 setMoney = false;77 this.notify();78 }79 80 }
但是如果存钱和取钱包含多个线程的话 if 就不行 只有使用while才能满足条件
1 package com.thread; 2 /** 3 * 模拟同步取款的问题 4 * @author dr 5 * 6 */ 7 public class ThreadTest { 8 public static void main(String[] args) { 9 final Account account = new Account();10 //取出200 两个取钱的线程11 for(int i=0;i<2;i++){12 new Thread(new Runnable() {13 @Override14 public void run() {15 for(int i=0;i<3;i++){16 try {17 Thread.sleep(500);18 } catch (InterruptedException e) {19 // TODO Auto-generated catch block20 e.printStackTrace();21 }22 account.getMoney(200);23 }24 }25 }).start();26 }27 //存入300 两个存钱的线程28 for(int i=0;i<2;i++){29 new Thread(new Runnable() {30 @Override31 public void run() {32 for(int i=0;i<3;i++){33 try {34 Thread.sleep(500);35 } catch (InterruptedException e) {36 // TODO Auto-generated catch block37 e.printStackTrace();38 }39 account.setMoney(300);40 }41 }42 }).start();43 }44 }45 }46 class Account {47 48 private int balance = 1000;49 //先存钱50 private boolean setMoney = true;51 public synchronized void getMoney(int count){52 while(setMoney){53 try {54 this.wait();55 } catch (InterruptedException e) {56 // TODO Auto-generated catch block57 e.printStackTrace();58 }59 }60 int result =balance - count;61 if(result >= 0){62 balance = result;63 System.out.println(Thread.currentThread().getName()+"取出:"+count+"元,剩余:"+balance);64 }else{65 System.out.println("余额不足...");66 }67 setMoney = true;68 this.notifyAll();69 }70 public synchronized void setMoney(int count){71 while(!setMoney){72 try {73 this.wait();74 } catch (InterruptedException e) {75 // TODO Auto-generated catch block76 e.printStackTrace();77 }78 }79 balance += count;80 System.out.println(Thread.currentThread().getName()+"存入:"+count+"元,剩余:"+balance);81 setMoney = false;82 this.notifyAll();83 }84 85 }
分析:
有A、B、C、D四个线程 AB存钱线程,CD取钱线程,使用if的时候,假设A执行,看标志无需wait 执行完成后 改标志为 取 ,A B 都先获得执行权 但状态不符合,
处于等待状态 A B 无执行权, C获得执行权后 执行完成后 更改状态为存 同时唤醒 A ,D获得执行权也处于等待状态。
现在只有A有执行权 A执行完成后 更改标志 先唤醒 B,B此时无需检查标志了紧接执行存款 从而导致 出现连续两次 取款的情形
使用while的时候 ,虽然B被唤醒 但经while(flag) 又会 检查标志 使其处于等待状态 使用while 要使用notifyAll 否则会出现全部等待状态
线程(while 和 if 剖析)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。