java并发中的wait(),notify(),notifyAll()方法和Condition接口

  • 方法简单介绍
    wait()方法:当一个任务在方法里遇到了对wait()的调用,线程的执行将被挂起,并释放锁。因此另外一个任务可以获得这个锁。也正因为如此,所以应该在同步代码块或synchronized方法里调用用该方法
    notify()/notifyAll()方法:使等待的线程重新获得锁,从wait()方法中恢复执行,notify()将随机恢复一个等待的线程,而notifyAll()方法将恢复所有等待的线程
    注意:一个线程被唤醒不代表立即获取了对象的锁,只有等调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,且必须执行完当前线程的任务,其余线程才可获得锁执行

  • 一个简单例子

            public class Test {
                public static Object object = new Object();
                public static void main(String[] args) {
                    Thread1 thread1 = new Thread1();
                    Thread2 thread2 = new Thread2();
    
                    thread1.start();
    
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    thread2.start();
                }
    
    
                static class Thread1 extends Thread{
                    @Override
                    public void run() {
                        synchronized (object) {
                            try {
                                object.wait();
                            } catch (InterruptedException e) {}
                            System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
                        }
                    }
                }
    
    
                static class Thread2 extends Thread{
                    @Override
                    public void run() {
                        synchronized (object) {
                            object.notify();
                            System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
                        }
                        System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");
                    }
                }
            }
    thread1执行任务以后将被挂起,然后thread2执行任务,唤醒线程1,但thread2必须执行完同步块还有任务以后,thread1才能从wait()中恢复
    
  • 用wait()/notify()方法模拟生产者与消费者
    生产者:

            import java.util.ArrayList;
    
            /**
             * @author hetiantian
             * 模拟生产者生产食物
             */
            public class Producer implements Runnable {
                //一次最多只能生产五个,如果到达五个了就需等待消费者把它吃了才能继续生产
                private static ArrayList<Food> foods = new ArrayList<>(5);
                static int id;  //事物标记
    
                public Producer(ArrayList<Food> foods) {
                    this.foods = foods;
                }
    
                //模拟生产的过程
                public static void productFood() throws InterruptedException {
                    while (true) {
                        Food f = new Food(id++);
    
                        synchronized (foods) {
                            if (foods.size() >= 5) {
                                foods.wait();  //如果大于等于6将被挂起,只有被消费了以后才会继续执行下一步的操作
                            } else {
                                foods.add(f);
                                System.out.println("生产了:" + f);
                            }
                        }
    
                    }
                }
    
                @Override
                public void run() {
                    try {
                        productFood();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
    消费者:
    
        import java.util.ArrayList;
    
        /**
         * @author hetiantian
         * 模拟消费者线程
         */
        public class Consumer implements Runnable {
            private static ArrayList<Food> foods = new ArrayList<>(5);
    
            public Consumer(ArrayList<Food> foods) {
                this.foods = foods;
            }
    
            public static void eatFood() throws InterruptedException {
                while (true) {
                    int last = foods.size() - 1;
                    Food f;
    
                    synchronized (foods) {
                        if (last < 0) {
                            foods.notify();  //如果吃光了则释放锁让生产者继续执行
                        } else {
                            f = foods.get(last);
                            System.out.println("消费了:" + f);
                            foods.remove(last);
                        }
                    }
    
                }
    
            }
    
            @Override
            public void run() {
                try {
                    eatFood();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    测试类:
    
    import java.util.ArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @author hetiantian
     * 消费者生产者测试类
     */
    public class ProductAndConsumerTest {
        private static ArrayList<Food> foods = new ArrayList<>(5);
        public static void main(String[] args) throws InterruptedException {
    
    
            Producer p = new Producer(foods);
            Consumer c = new Consumer(foods);
    
    
            ExecutorService es = Executors.newCachedThreadPool();
            es.execute(p);
            es.execute(c);
            TimeUnit.SECONDS.sleep(7);
            //关闭任务
            es.shutdownNow();
    
    
        }
    }
    
  • Condition简单介绍:
    Condition也提供了类似Object的监控方法,与Lock配合实现等待/通知模式没大吧是使用方式和功能特性上还是有差别的
    Condition的await()、signal()这种方式实现线程间协作更加安全和高效。Conditon中的await()对应Object的wait(),Condition中的signal()对应Object的notify(),Condition中的signalAll()对应Object的notifyAll()。因此更推荐使用Condition.
    Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
    调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值