Object object=new Object();
//线程1
Thread thread=new Thread(()->{
synchronized (object){
System.out.println("1");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("3");
}
});
//线程2
Thread thread2=new Thread(()->{
synchronized (object){
System.out.println("2");
object.notifyAll();
}
});
thread.start();
thread2.start();
创建了2个线程,object表示需要抢的锁,2个线程谁先抢到object锁谁就先执行,不是说thread.start()在thread2.start()前面就会先执行,有可能是thread2线程先执行。
如果thread线程抢到锁,先输出“1”,然后调用锁的wait()方法,注意这里必须是调用锁的wait方法,就是object.wait(),注意一定要捕获异常不然报错,一旦调用了wait方法,thread线程进入等待,就会释放锁,object被释放了,然后线程thread2就会拿到object锁,开始执行,输出“2”,然后调用notifyAll()方法,表示唤醒所有以object为锁的线程,于是thread线程被唤醒执行输出“3”,notify()方法表示随机唤醒一个以object为锁的线程。
如果thread2线程先抢到锁,先输出“2”,然后唤醒所有以object为锁的线程,但目前没有以object为锁的线程在等待,执行完thread2后,释放锁,thread线程拿到锁,输出“1”,然后进入等待,释放锁,由于thread2线程已经执行完销毁了,所以没人来唤醒以object为锁的线程,于是无法输出“3”,可以通过主线程如main方法获取锁然后唤醒。
如果线程需要的锁不同的话是不会等待的,唤醒也只会唤醒使用相同锁的线程。
注意,wait方法和notify方法都要在synchronized的范围内使用,超过了括号范围使用报错。
也可以使用wait(long),传入一个long类型的值,到时间后会自动唤醒当前线程。
Object o=new Object();
Thread thread=new Thread(()->{
synchronized(o){
System.out.println("1");
try {
o.wait();
Thread.sleep(2000);
System.out.println("3");
} catch (InterruptedException e) {
}
}
});
Thread thread2=new Thread(()->{
synchronized(o){
System.out.println("2");
o.notify();
}
});
thread.start();
thread2.start();
如果线程thread输出“1”后,wait方法进入等待,后面的sleep和输出“3”就不会执行,会等到线程thread2唤醒后才会执行。
Object o=new Object();
Thread thread=new Thread(()->{
synchronized(o){
System.out.println("1");
try {
Thread.sleep(2000);
System.out.println("3");
o.wait();
} catch (InterruptedException e) {
}
}
});
Thread thread2=new Thread(()->{
synchronized(o){
System.out.println("2");
o.notify();
}
});
thread.start();
thread2.start();
sleep方法并不会释放锁,会在当前线程等待,thread2线程无法拿到锁无法执行。wait方法会释放锁。sleep虽然放弃了cpu的使用权但是其他人也用不了,wait放弃了cpu使用权,其他人可以用。sleep是Thread的静态方法,wait和notify是Object的成员方法,每个对象都有。