线程通信
1.notify、wait、notifyall
notify方法是唤醒一个被阻塞的线程,若有多个线程被阻塞,先唤醒优先级高的
notifyall是唤醒所有线程
wait是阻塞一个线程,该线程阻塞后会释放锁
这三个方法必须在同步代码块或者同步方法中使用,并且调用者必须是同步代码块或者同步方法的同步监视器
实现1~100线程1、2的轮流打印
package Test1; /** * @author rook1e * @creat 2022/1/12 */ class Number implements Runnable { private int number = 1; @Override public void run() { while (true) { synchronized (this) { notify();//唤醒 if (number <= 100) { System.out.println(Thread.currentThread().getName() + ":" + number); number++; } else { break; } try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public class ComTest { public static void main(String[] args) { Number number = new Number(); Thread t1 = new Thread(number); Thread t2 = new Thread(number); t1.setName("线程1"); t2.setName("线程2"); t1.start(); t2.start(); } }
这段代码有以下几个很值得注意的点
0.synchronized(this) 只new了一个Number对象,并且线程共用一个numer对象,所以对象是唯一的,所以当前对象this也是唯一的,因此锁唯一。
1.notify唤醒线程后,不会出现线程安全问题吗?答案是不会,当线程1打印完1后阻塞,线程2拿到同步锁,进入同步代码块,唤醒线程1,但此时线程2已经拿到同步锁,线程1无法进入同步代码块,也就没有线程安全问题
2.使用wait方法后,线程会失去同步锁,线程进入阻塞状态
sleep() 和 wait()的异同
相同点:一旦使用会让线程进入阻塞状态
不同点:1.声明位置不同,Thread类中声明sleep()方法,Object类中声明wait()方法
2.调用要求不同,sleep方法可以在任何需要的场景下调用,wait方法只能使用在同步代码块或者同步方法中
3.使用结果不同,sleep方法不会释放同步监视器(锁),wait方法使用后会释放同步监视器。