多线程:线程不安全案例(买票、银行取钱、集合),
分享于 点击 26707 次 点评:265
多线程:线程不安全案例(买票、银行取钱、集合),
1、买票案例
(1)实现接口,创建买票的线程:
public class BuyTickets implements Runnable { private int ticketNum=10; boolean flag=true; @Override public void run() { while (flag){ buy(); } } private void buy(){ if(ticketNum<=0){ flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNum--+"张票"); } }
(2)创建三个线程进行测试:
public class Test { public static void main(String[] args) { BuyTickets buyTickets=new BuyTickets(); new Thread(buyTickets,"zhai").start(); new Thread(buyTickets,"zhang").start(); new Thread(buyTickets,"zhao").start(); } }
(3)测试结果:
zhao拿到了第10张票
zhang拿到了第10张票
zhai拿到了第9张票
zhai拿到了第8张票
zhang拿到了第7张票
zhao拿到了第6张票
zhai拿到了第5张票
zhang拿到了第4张票
zhao拿到了第3张票
zhai拿到了第2张票
zhang拿到了第1张票
zhao拿到了第0张票
zhai拿到了第-1张票
十号票被卖两次的原因是:
zhang拿到第10张票后,发现数量是大于0的,可以继续执行,但是没有抢占到CPU资源,接着,zhao拿到第10张票以后,获得了CPU资源,执行完毕后,才轮到zhang执行
zhai得到-1票的原因:
有多个人拿到了同一张票,在第1个减一后变为1,第二个人减一后变为0,第三个人减一后变为-1
2、银行取钱
(1)继承Thread类,创建取钱的线程:
public class BankTest extends Thread{ Account account; int drawingMoney;//取出的金额 int nowMoney;//现金 public BankTest(Account account,int drawingMoney,String name){ super(name); this.account=account; this.drawingMoney=drawingMoney; } public void run(){ //判断是否有余额 if(account.money-drawingMoney<0){ System.out.println("余额不足"); return; } try { Thread.sleep(1000);//放大问题的发生性 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("余额:"+account.money); account.money=account.money-drawingMoney;//余额 nowMoney=nowMoney+drawingMoney; System.out.println(this.getName()+"现金:"+nowMoney); } }
(2)创建账户类:
public class Account { int money;//余额 String name;//名字 public Account(int money, String name) { this.money = money; this.name = name; } }
(3)创建测试类:
public class Test { public static void main(String[] args) { Account account=new Account(1000,"工资"); BankTest bankTest1=new BankTest(account,150,"tom"); BankTest bankTest2=new BankTest(account,200,"jack"); bankTest1.start(); bankTest2.start(); } }
(4)测试结果又几种不同的情况:
余额:1000 tom现金:150 余额:1000 jack现金:200
余额:1000 余额:1000 tom现金:150 jack现金:200
余额:1000 jack现金:200 余额:800 tom现金:150
余额:1000 余额:1000 jack现金:200 tom现金:150
产生这种情况的原因是,可能两个线程同时调用了run方法,但是一个线程获得了CPU,一个线程未获得CPU没有办法执行,只有它执行之后另外一个等待的线程才能执行。
3、线程不安全的集合
public class UnSafeList { public static void main(String[] args) { List<String> list=new ArrayList<String>(); for(int i=0;i<10000;i++){ new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
两个线程同一瞬间操作了同一个位置,将元素覆盖掉了,因此,集合的长度小于预期值。
相关文章
- 暂无相关文章
用户点评