wait和notify方法

注意:

1,wait和notify方法不是线程对象的方法,是Object类中的方法,是Java中任何一个Java对象都有的方法。


2,wait()方法的使用和作用:

        Object o=new Object();

        o.wait();

表示:

        o.wait();方法的调用,会让正在o对象上活动的线程进入“等待状态”,

        无限期的等待,直到被唤醒

注意wait方法不能单独使用,得和synchronized一起使用。

     

3,notify()方法的使用和作用:

     Object o=   new Object();

        o.notify();

    表示:

        唤醒正在o对象上等待的线程。

还有一个notifyAll()方法:

        这个方法是唤醒o对象上处于等待的所有线程。

生产者消费者模型: 

 生产者类:

public class Producer implements Runnable {
    
    List list;

    public Producer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        //一直生产(使用死循环来模拟一直生产)
        for (int i=0;i<10;i++){
            //给仓库对象list加锁
            synchronized (list) {
                if (list.size() > 0) {//大于0,说明仓库有1个元素了。
                    try {
                        //当前线程进入等待状态,并且释放Producer之前占有的list集合的锁
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //程序能够执行到这里说明仓库是空的,可以生产了
                String s = new String("电脑");
                list.add(s);
                System.out.println(Thread.currentThread().getName() + "生产了--->" + s);
                list.notify();
            }
        }
    }
}

消费者类:

public class Consumer implements Runnable{

    List list;

    public Consumer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
       for (int i=0;i<10;i++){
           synchronized (list){
               if (list.size()==0){
                   try {
                       list.wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               Object obj = list.remove(0);
               System.out.println(Thread.currentThread().getName()+"消费了--->"+obj);
               list.notify();
           }
       }
    }
}

测试: 

public class Test07 {
    public static void main(String[] args) {
       List<Object> list = new ArrayList<>();

        Thread t = new Thread(new Producer(list));
        Thread t1= new Thread(new Consumer(list));
        t.setName("t");
        t1.setName("t1");

        t.start();
        t1.start();
    }
}

java wait timeout 怎么获取超时_java

 

 

join():

推荐文章:


实例方法,使当前线程进入阻塞,直到使用join方法的线程对象执行完毕后,才能执行。


1,可以输入阻塞时间
public final synchronized void join(long millis)

2,等待被join的线程的时间最长为mills毫秒加nanos毫微秒。
        很少用,单位太小软件和硬件都无法精确。   
public final synchronized void join(long millis, int nanos)

3,一直阻塞,直至线程被销毁
public final void join() throws InterruptedException { join(0); }
 join(0)调用的其实是==1在的方法
public static void main(String[] args) {
    Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("子线程执行");
			}
		};
    Thread thread1 = new Thread(runnable);
    Thread thread2 = new Thread(runnable);
    thread1.start();
    thread2.start();
    try {
        //主线程开始等待子线程thread1,thread2
        thread1.join();
        thread2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    //等待两个线程都执行完(不活动)了,才执行下行打印
  `  System.out.println("执行完毕")`;;
}

 public final synchronized void join(long millis):源码

join方法的底层实际上还是调用了wait()方法,通过wait()方法实现线程阻塞等待,join内部调用 Object的native wait方法是将当前线程阻塞,而不是将当前调用的对象的线程阻塞

(要注意wait方法是会释放锁的,说明此时可以有另外的线程调用这个“当前线程”)


那么这里有个问题,阻塞完成后,如何通知呢?我们知道调用wait阻塞的线程,需要notify()或者notifyAll来进行唤醒,这里并没有显式调用这两个方法,那是如何实现的呢?


这里涉及一个知识:

在java中,Thread类线程执行完run()方法后,会自动执行notifyAll()方法。

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }