方法简单介绍
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之间才可以使用
java并发中的wait(),notify(),notifyAll()方法和Condition接口
最新推荐文章于 2022-06-13 21:35:19 发布