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;
}

 

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