多线程模拟银行取款
java源码展示:
银行:Account.java
package testsynchrozied; /** * 账户类 * @author superdrew * */ public class Account { private int balance = 600;//余额 //显示余额 public int getBalance(){ return balance; } //取款 public void draw(int money){ balance = balance - money; } }
银行线程:AccountRunnable.java
package testsynchrozied; public class AccountRunnable implements Runnable{ Account account = new Account();//取款的账户 Object obj = new Object(); public void run() { synchronized(obj){ //synchronized 同步 加锁 默认是 open状态 --close()--open //省略 300行代码 if(account.getBalance()>=400){//余额大于400就取钱 try { Thread.sleep(1);//第一个线程 进入阻塞,取钱了 线程死亡了 //第二个线程 进入阻塞 取钱了 线程死亡了 } catch (InterruptedException e) { e.printStackTrace(); } account.draw(400); System.out.println("取款成功,当前余额:"+account.getBalance()+"当前线程为:"+Thread.currentThread().getName()); }else{ System.out.println("余额不足,当前余额:"+account.getBalance()+"当前线程为:"+Thread.currentThread().getName()); } //省略 500行代码 } //解锁 释放锁 } public void method1(){ synchronized(obj){ } } public void method2(){ synchronized(account){ } } public void method3(){ synchronized(account){ } } }
测试银行取款主线程:TestSynchronized.java
package testsynchrozied; /** * 功能:多个用户同时对一个账户取款 * 使用线程的同步 * * 1.设计一个账户类 余额,取款,显示余额 * 2.取款的线程 * 3.用户同时取款 * * 解决方案1:同步代码块 synchronized(account){ .... } * * 总结:1.认识同步监视器 account * synchronized(同步监视器){ ... } * 1.必须是引用类型的数据,不能是基本数据类型 * 2.在同步代码块中,不要改变引用类型数据的值,属性的值可以修改 * 3.尽量不要使用String 和 包装类做同步监视器,除非代码块中不会改变其内容 * 4.一般是使用共享资源作为同步监视器 (account) * 5.可以新建一个专门的同步监视器 Object 没有具体的业务含义 * * 2.之前见过的同步监视器 * StringBuffer Hashtabale vector * * 3.同步代码块的执行过程 * 1.第一个线程来到同步代码块,发现同步监视器是open状态,需要close,进去执行里面的代码 * 2.执行里面的代码发生了一些情况 ,切换(阻塞,就绪),第一个线程失去cpu,锁 还是close * 3.第二个线程来到同步代码块,发现同步监视器是close状态,无法执行,其中的代码也不能执行, * 第二个线程进入阻塞状态 * 4.第一个线程再次获取cpu,接着执行后续代码,执行完毕,锁 open 第一个线程进入死亡状态 * 5.第二个线程再次获取cpu,又同步代码块,发现锁是open状态,执行后续代码.重复第一个线程的过程 * * 4.线程同步的有点和缺点 * 优点:安全 * 缺点:效率低下,有可能出现死锁 * * 5.多个同步代码块使用的是同一个同步监视器(锁),锁住其中一个代码块同时也会锁住其它的所有使用该同步监视器(锁)代码块 * 其它线程无法访问其中任何一个代码块 * 但是没有锁住其它的同步监视器代码块 */ public class TestSynchronized { public static void main(String[] args) { AccountRunnable ar = new AccountRunnable(); Thread th1 = new Thread(ar); th1.setName("Drew"); Thread th2 = new Thread(ar); th2.setName("Super"); th1.start(); th2.start(); } }
结果展示: