java-study Thread線程、synchronized同步鎖、await()/notify()

 demo1:

package com.TestThread;

public class Test {
    public static void main(String[] args) {
        Account a0 = new Account();
        Account a1 = new Account();
        User u0 = new User(a0, 2000);
        User u1 = new User(a1, 2000);

        Thread t0 = new Thread(u0);
        Thread t1 = new Thread(u1);
        t0.start();
        t1.start();
    }
}

class Account {
    private static int balance = 3000;

    /**
     *  synchronized加在成員方法上只能鎖調用當前方法的對象,例如man方法中如果u0、u1接口構造中傳入的不是同一個Account對象的話,無法使用實現同步鎖。
     *  要想所有實例成員共用一個同步鎖可以將該方法修飾爲static
     */
    public synchronized void TakeBalance(int m) {
        String tname = Thread.currentThread().getName();
        System.out.println(tname+"當前餘額"+balance);
        if(m < balance) {
            System.out.println(tname+"取款2000");
            System.out.println(tname+"取款中。。。");
            balance -= m;
            System.out.println(tname+"取款成功");
            System.out.println(tname+"餘額剩餘"+balance);
        }else{
            System.out.println(tname+"取款失敗,餘額不足");
            System.out.println(tname+"餘額剩餘"+balance);
        }
    }

    /**
     * 代碼塊同步鎖,synchronized(instance),加在代碼塊前面,傳入的參數爲一個實例對象(或者this),表示對該對象使用同一個鎖。
     *
     */
    public void TakeBalance2(int m) {
       synchronized (this) {
           String tname = Thread.currentThread().getName();
           System.out.println(tname+"當前餘額"+balance);
           if(m < balance) {
               System.out.println(tname+"取款2000");
               System.out.println(tname+"取款中。。。");
               balance -= m;
               System.out.println(tname+"取款成功");
               System.out.println(tname+"餘額剩餘"+balance);
           }else{
               System.out.println(tname+"取款失敗,餘額不足");
               System.out.println(tname+"餘額剩餘"+balance);
           }
       }
    }
}

class User implements Runnable {
    public User(Account a, int m) {
        money = m;
        account = a;
    }
    private int money;
    private Account account;

    @Override
    public void run() {
//        account.TakeBalance(money);
        account.TakeBalance2(money);
    }
}

demo2:

package com.TestThread;

/**
 * 場景說明:生產者->供應商店,消費者->從商店消費
 * 需求說明:商店商品數量最多存放10個,數量少於4個時生產者供應商品;消費者在商品數量大於0時都可以消費,否則等待生產者供應;
 *
 * 疑惑點:在兩個線程中,當此處while在代碼塊鎖內的時候控制檯輸出規律是一致的,都是 生產滿5個->消費至0->生產滿5個->消費至0...,而目前這樣打印出來是會出現隨機的,即生產完一個就有可能會馬上被消費。
 */
public class Test2 {
    public static void main(String[] args) {
        Shop shop = new Shop();
        new Thread(new Runnable() {//內部類直接實現接口
            @Override
            public void run() {
                while(true) {
                    synchronized (shop) {
                        if(shop.productionNum < 5) {
                            System.out.println("開始生產,當前剩餘商品:"+shop.productionNum);
                            shop.productionNum++;
                            System.out.println("生產完成,當前剩餘商品:"+shop.productionNum);

                            shop.notify();//生產完畢後,喚醒當前正在等候的線程(消費者)
                        }else{
                            System.out.println("商品數量充足 暫不生產,當前剩餘商品:"+shop.productionNum);
                            try {
                                shop.wait();//當前線程掛起並放棄cpu、同步資源,使別的線程可訪問並修改共享資源,而當前線程等候。
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

            }
        },"生產者").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    synchronized (shop) {
                        if(shop.productionNum > 0) {
                            System.out.println("開始消費,當前剩餘商品:"+shop.productionNum);
                            shop.productionNum--;
                            System.out.println("消費完成,當前剩餘商品:"+shop.productionNum);

                            shop.notify();//消費完畢後,喚醒當前正在等候的線程(生產者)
                        }else{
                            System.out.println("商品數量不足 不能消費,當前剩餘商品:"+shop.productionNum);
                            try {
                                shop.wait();//當前線程掛起並放棄cpu、同步資源,使別的線程可訪問並修改共享資源,而當前線程等候。
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        },"消費者").start();
    }
}

class Shop {
    public static int productionNum = 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章