码迷,mamicode.com
首页 > 编程语言 > 详细

线程(while 和 if 剖析)

时间:2014-11-08 23:31:23      阅读:320      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   os   使用   sp   

那存钱取钱为例:

  要求实现一次存一次取的操作 不可出现连续存或连续取;

  如果只有存钱和取钱各自只有一个线程在操作使用 if 的话可以满足要求:

  

bubuko.com,布布扣
 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         new Thread(new Runnable() {
12             @Override
13             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 block
19                         e.printStackTrace();
20                     }
21                     account.getMoney(200);
22                 }
23             }
24         }).start();
25         //存入300
26         new Thread(new Runnable() {
27             @Override
28             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 block
34                         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 block
52                 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 block
71                     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 }
View Code

  但是如果存钱和取钱包含多个线程的话 if 就不行 只有使用while才能满足条件

bubuko.com,布布扣
 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                 @Override
14                 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 block
20                             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                 @Override
31                 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 block
37                             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 block
57                 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 block
76                     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 }
View Code

分析:
  有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 剖析)

标签:style   blog   http   io   color   ar   os   使用   sp   

原文地址:http://www.cnblogs.com/Wen-yu-jing/p/4084137.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!