Java—wait 方法和notify方法

1. wait()—痴汉方法

wait()方法就是使线程停止运行,会释放对象锁。

wait()方法是从运行态回阻塞态。
notifi( ) 方法是从阻塞态回运行态。

  1. wait()方法会使当前线程调用该方法后进行等待,并且将该线程置入锁对象的等待队列中,直到接到通知或被中断为止。
  2. wait()方法只能在同步方法或同步代码块中调用,如果调用wait()时没有适当的锁,会抛出异常。
  3. wait()方法执行后,当前线程释放锁,其他线程可以竞争该锁。
  • wait()之后的线程继续执行有两种方法:
  1. 调用该对象的notify()方法唤醒等待线程。
  2. 线程等待时调用interrupt()中断该线程。

wait(long time) :如果到了预计时间还未被唤醒,线程将继续执行。

class MyThread implements Runnable{
    private Object object;
    private boolean flag;

    public MyThread(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }

    public void waitMethod() {
        synchronized (object) {
            System.out.println("wait方法开始..." + Thread.currentThread().getName());
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束..." + Thread.currentThread().getName());
        }
    }
    public void notifyMethod(){
        synchronized (object) {
            System.out.println("notify方法开始..." + Thread.currentThread().getName());
            object.notify();
            System.out.println("notify方法结束..." + Thread.currentThread().getName());
        }
    }
    public void run(){
        if(flag){
           this.waitMethod();
        }else{
           this.notifyMethod();
        }
    }
}
public class Object {
    public static void main(String[] args)throws InterruptedException{
        Object obj = new Object();
        MyThread thread1 = new MyThread(obj,true);
        MyThread thread2 = new MyThread(obj,false);
        Thread waitThread = new Thread(thread1,"等待线程");
        Thread notifyThread = new Thread(thread2,"唤醒线程");
        waitThread.start();
        Thread.sleep(1000);
        notifyThread.start();
    }
}

运行结果:
wait方法开始...等待线程
notify方法开始...唤醒线程
notify方法结束...唤醒线程
wait方法结束...等待线程

2. notify()方法

  1. notify()方法必须在同步方法或同步代码块中调用,用来唤醒等待在该对象上的线程,如果有多个线程等待,则任意挑选一个线程唤醒。
  2. notify()方法执行后,唤醒线程不会立刻释放锁,要等唤醒线程全部执行完毕后才释放对象锁。
class MyThread implements Runnable{
    private Object object;
    private boolean flag;

    public MyThread(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }

    public void waitMethod() {
        synchronized (object) {
            System.out.println("wait方法开始..." + Thread.currentThread().getName());
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束..." + Thread.currentThread().getName());
        }
    }
    public void notifyMethod(){
        synchronized (object) {
            System.out.println("notify方法开始..." + Thread.currentThread().getName());
            object.notify();
            System.out.println("notify方法结束..." + Thread.currentThread().getName());
        }
    }
    public void run(){
        if(flag){
           this.waitMethod();
        }else{
           this.notifyMethod();
        }
    }
}
public class Object {
    public static void main(String[] args)throws InterruptedException{
        Object obj = new Object();
        MyThread thread1 = new MyThread(obj,true);
        MyThread thread2 = new MyThread(obj,false);
        for(int i = 0;i<5;i++) {
            Thread threadi = new Thread(thread1, "等待线程"+i);
            threadi.start();
        }
        Thread notifyThread = new Thread(thread2,"唤醒线程");
        Thread.sleep(1000);
        notifyThread.start();
    }
}
wait方法开始...等待线程0
wait方法开始...等待线程1
wait方法开始...等待线程2
wait方法开始...等待线程3
wait方法开始...等待线程4
notify方法开始...唤醒线程
notify方法结束...唤醒线程
wait方法结束...等待线程0
//当有多个线程同时等待时,notify方法任意挑选一个唤醒。

wait()和notify()均用于同步方法或同步代码块并且必须是内建锁。

3. notifyAll()

唤醒所有在该对象上等待的线程。

class MyThread implements Runnable{
    private Object object;
    private boolean flag;

    public MyThread(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }

    public void waitMethod() {
        synchronized (object) {
            System.out.println("wait方法开始..." + Thread.currentThread().getName());
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束..." + Thread.currentThread().getName());
        }
    }
    public void notifyMethod(){
        synchronized (object) {
            System.out.println("notify方法开始..." + Thread.currentThread().getName());
            object.notifyAll();
            System.out.println("notify方法结束..." + Thread.currentThread().getName());
        }
    }
    public void run(){
        if(flag){
           this.waitMethod();
        }else{
           this.notifyMethod();
        }
    }
}
public class Object {
    public static void main(String[] args)throws InterruptedException{
        Object obj = new Object();
        MyThread thread1 = new MyThread(obj,true);
        MyThread thread2 = new MyThread(obj,false);
        for(int i = 0;i<5;i++) {
            Thread threadi = new Thread(thread1, "等待线程"+i);
            threadi.start();
        }
        Thread notifyThread = new Thread(thread2,"唤醒线程");
        Thread.sleep(1000);
        notifyThread.start();
    }
}
运行结果:
wait方法开始...等待线程0
wait方法开始...等待线程1
wait方法开始...等待线程2
wait方法开始...等待线程3
wait方法开始...等待线程4
notify方法开始...唤醒线程
notify方法结束...唤醒线程
wait方法结束...等待线程4
wait方法结束...等待线程3
wait方法结束...等待线程2
wait方法结束...等待线程1
wait方法结束...等待线程0

4.线程阻塞

  1. 调用sleep()方法,主动放弃占有的CPU,不会释放对象锁。
  2. 调用阻塞式IO方法(read()、write()),在该方法返回前,线程阻塞。
  3. 线程试图获取一个monitor,但该monitor被其他线程所持有导致阻塞。
  4. 线程等待某个通知,即调用wait(),释放对象锁。
  5. 调用线程suspend(),将线程挂起,容易导致死锁,已被废弃。
    这五个线程会从运行状态到阻塞状态。

5. monitor 的两个队列

每个monitor都有两个队列,一个称为同步队列,一个称为等待队列。

  • 同步队列中存放了因为竞争monitor失败导致阻塞的线程,这些线程等待CPU调度再次竞争锁。
  • 等待队列存放所有调用wait()方法导致线程等待的线程,唤醒后进入同步队列竞争锁。

猜你喜欢

转载自blog.csdn.net/qq_41420688/article/details/84296459