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