java wait是怎样的呢?下面就让我们一起来了解一下吧:
wait()方法是属于java中的一个方法,它的作用是能够让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。直到其他线程调用此对象的notify()方法或者notifyAll()方法,当前线程被唤醒(也就是进入“就绪状态”)。
说明:
notify()和notifyAll()方法的作用,则是用于唤醒当前对象上的等待线程;notify()方法是唤醒单个线程,而notifyAll()是唤醒所有的线程。
参考范例:
packagecom.citi.test.mutiplethread.demo0503;importjava.util.Date;publicclassWaitTest{publicstaticvoidmain(String[]args){ThreadAt1=newThreadA("t1");System.out.println("t1:"+t1);synchronized(t1){try{//启动线程System.out.println(Thread.currentThread().getName()+"startt1");t1.start();//主线程等待t1通过notify唤醒。System.out.println(Thread.currentThread().getName()+"wait()"+newDate());t1.wait();//不是使t1线程等待,而是当前执行wait的线程等待System.out.println(Thread.currentThread().getName()+"continue"+newDate());}catch(Exceptione){e.printStackTrace();}}}}classThreadAextendsThread{publicThreadA(Stringname){super(name);}@Overridepublicvoidrun(){synchronized(this){System.out.println("this:"+this);try{Thread.sleep(2000);//使当前线程阻塞1秒}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"callnotify()");this.notify();}}}以上就是小编的分享了,希望能够帮助到大家。
Java的wait和notify
Java中的wait和notify是线程同步机制的两个关键字,用于协调多个线程的执行顺序和相互之间的通信。本文将介绍wait和notify的基本概念、使用方法和注意事项。
wait的概念wait方法是Object类中定义的一个实例方法,用于让当前线程进入等待状态,直到另一个线程通知它继续执行或等待超时。wait方法的基本语法如下:
public final void wait() throws InterruptedException
当调用wait方法时,当前线程会释放它所持有的对象的锁,并进入等待状态,直到其他线程通过notify或notifyAll方法唤醒它。如果等待过程中被中断,wait方法会抛出InterruptedException异常。
notify的概念notify方法也是Object类中定义的一个实例方法,用于通知正在等待某个对象的线程继续执行。notify方法的基本语法如下:
public final void notify()
当调用notify方法时,它会随机唤醒一个正在等待该对象的线程,使其从wait方法中返回,并重新尝试获取对象的锁。如果没有等待该对象的线程,调用notify方法不会产生任何效果。
wait和notify的使用方法wait和notify通常是配合使用的,以实现多个线程之间的协作和通信。下面是一个简单的例子,演示了wait和notify的使用方法:
public class ThreadDemo { private Object lock = new Object(); public void waitMethod() { synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void notifyMethod() { synchronized (lock) { lock.notify(); } }}
在这个例子中,waitMethod方法中的synchronized块获取了lock对象的锁,并调用了lock.wait()方法,使当前线程进入等待状态。notifyMethod方法中的synchronized块同样获取了lock对象的锁,并调用了lock.notify()方法,以通知等待lock对象的线程继续执行。
wait和notify的注意事项在使用wait和notify时,需要注意以下几点:
下面是一个示例代码,演示了为什么必须使用循环检查条件:
public class ThreadDemo { private Object lock = new Object(); private boolean flag = false; public void waitMethod() { synchronized (lock) { if (!flag) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("waitMethod executed."); } } public void notifyMethod() { synchronized (lock) { flag = true; lock.notify(); System.out.println("notifyMethod executed."); } }}
在这个例子中,waitMethod方法中使用了单独的if语句来检查条件,而没有使用循环检查条件。当调用notifyMethod方法时,它会将flag变量设置为true,并通知等待lock对象的线程继续执行。
然而,在多线程环境下,存在线程竞争和信号丢失的问题。假设在调用notifyMethod方法之前,有两个线程A和B都调用了waitMethod方法并进入了等待状态。当notifyMethod方法被调用时,它只能随机唤醒一个线程,如果唤醒的是线程A,那么线程A会从wait方法中返回并执行后续的操作,但线程B仍然处于等待状态,因为它没有收到通知。
因此,在使用wait和notify时,必须使用循环检查条件,以确保在唤醒线程后再次检查条件,避免出现线程竞争和信号丢失的问题。正确的waitMethod方法应该像下面这样:
public void waitMethod() { synchronized (lock) { while (!flag) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("waitMethod executed."); }}
在这个方法中,使用了while循环来检查条件,当条件不满足时,线程会继续等待。当唤醒线程后,再次检查条件,确保条件满足后才会继续执行。
经典的生产者和消费者模式通过notify和wait实现:
package concurrency;import java.util.LinkedList;import java.util.Queue;import org.apache.log4j.Logger;public class InterThreadCommunicationExample { public static void main(String args[]) { final Queue sharedQ = new LinkedList(); Thread producer = new Producer(sharedQ); Thread consumer = new Consumer(sharedQ); producer.start(); consumer.start(); }}public class Producer extends Thread { private static final Logger logger = Logger.getLogger(Producer.class); private final Queue sharedQ; public Producer(Queue sharedQ) { super("Producer"); this.sharedQ = sharedQ; } @Override public void run() { for (int i = 0; i < 4; i ) { synchronized (sharedQ) { //waiting condition - wait until Queue is not empty while (sharedQ.size() >= 1) { try { logger.debug("Queue is full, waiting"); sharedQ.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); } } logger.debug("producing : " i); sharedQ.add(i); sharedQ.notify(); } } }}public class Consumer extends Thread { private static final Logger logger = Logger.getLogger(Consumer.class); private final Queue sharedQ; public Consumer(Queue sharedQ) { super("Consumer"); this.sharedQ = sharedQ; } @Override public void run() { while(true) { synchronized (sharedQ) { //waiting condition - wait until Queue is not empty while (sharedQ.size() == 0) { try { logger.debug("Queue is empty, waiting"); sharedQ.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); } } int number = sharedQ.poll(); logger.debug("consuming : " number ); sharedQ.notify(); //termination condition if(number == 3){break; } } } }}Output:05:41:57,244 0 [Producer] DEBUG concurrency.Producer - producing : 005:41:57,260 16 [Producer] DEBUG concurrency.Producer - Queue is full, waiting05:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - consuming : 005:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - Queue is empty, waiting05:41:57,260 16 [Producer] DEBUG concurrency.Producer - producing : 105:41:57,260 16 [Producer] DEBUG concurrency.Producer - Queue is full, waiting05:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - consuming : 105:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - Queue is empty, waiting05:41:57,260 16 [Producer] DEBUG concurrency.Producer - producing : 205:41:57,260 16 [Producer] DEBUG concurrency.Producer - Queue is full, waiting05:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - consuming : 205:41:57,260 16 [Consumer] DEBUG concurrency.Consumer - Queue is empty, waiting05:41:57,260 16 [Producer] DEBUG concurrency.Producer - producing : 305:41:57,276 32 [Consumer] DEBUG concurrency.Consumer - consuming : 3
这就是 Java 中使用等待和通知方法进行线程间通信的简单示例的全部内容。您可以看到,生产者线程和使用者线程都在相互通信并使用共享队列共享数据,生产者在有项目可供使用时通知使用者,而使用者线程在完成消费后告诉生产者。