• 多线程模拟银行取款


    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();
    
        }
    }
    结果展示:

  • 相关阅读:
    poj2240
    poj1135
    poj1062
    poj3278
    2218 补丁vs错误
    必做: 1041、1024、1077、2218、1183(较难)
    poj2828
    poj3253
    洛谷P1122 最大子树和
    1074 食物链
  • 原文地址:https://www.cnblogs.com/superdrew/p/8093032.html
Copyright © 2020-2023  润新知