1.线程中的wait()方法与sleep()方法

  1. 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
  2. sleep()方法只是让出了CPU,并不会释放资源锁。wait会释放锁,暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。
  3. sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用。

2.线程中的wait()方法与notify()方法

  1. notify()唤醒等待的线程,如果监视器中只有一个等待线程,使用notify()可以唤醒。但是如果有多条线程notify()是随机唤醒其中一条线程,与之对应的就是notifyAll()就是唤醒所有等待的线程

3.线程中的await()方法与signal()方法

关键字synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待/通知模式。

ReentrantLock同样可以实现该功能,但是要借助于Condition对象。它具有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Condition(对象监视器)实例,线程对象可以注册在指定Condition中,从而有选择性的进行线程通知,在调度线程上更加灵活
通过ReentrantLock和Condition配合实现多个指定线程的等待和通知:

public class MyService {


    private Lock lock = new ReentrantLock();

    public Condition conditionA = lock.newCondition();  //对象监视器
    public Condition conditionB = lock.newCondition();

    public void awaitA() {
        try {
            lock.lock();
            System.out.println("thread " + Thread.currentThread().getName() + " wait begin,in awaitA method");
            conditionA.await(); //使用conditionA进行等待
            System.out.println("thread " + Thread.currentThread().getName() + " end wait,in awaitA method");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void awaitB() {
        try {
            lock.lock();
            System.out.println("thread " + Thread.currentThread().getName() + " wait begin,in awaitB method");
            conditionB.await();   //使用conditionB进行等待
            System.out.println("thread " + Thread.currentThread().getName() + " end wait,in awaitB method");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signalAll_A() {
        try {
            lock.lock();
            System.out.println("现在要通知所在在conditionA上等待的线程 " + Thread.currentThread().getName());
            conditionA.signalAll();  //通知所有在conditionA上等待的线程
        } finally {
            lock.unlock();
        }
    }

    public void signalAll_B() {
        try {
            lock.lock();
            System.out.println("现在要通知所在在conditionB上等待的线程 " + Thread.currentThread().getName());
            conditionB.signalAll();
        } finally {
            lock.unlock();
        }
    }
}
public class ThreadA extends Thread{

    private MyService service;

    public ThreadA(MyService service){
        super();
        this.service = service;
    }

    @Override
    public void run(){
        service.awaitA();
    }
}
public class ThreadB  extends Thread{

    private MyService service;

    public ThreadB(MyService service){
        super();
        this.service = service;
    }

    @Override
    public void run(){
        service.awaitB();
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        Thread.sleep(3000);
        service.signalAll_A();  //只通知在conditionA上等待的线程。
        service.signalAll_B();  //只通知在conditionB上等待的线程。
    }
}

 

执行结果
thread A wait begin,in awaitA method
thread B wait begin,in awaitB method
现在要通知所在在conditionA上等待的线程 main
现在要通知所在在conditionB上等待的线程 main
thread A end wait,in awaitA method
thread B end wait,in awaitB method

 

4.java中的ReentrantLock与synchronized

ReentrantLock对比synchronized的优势:时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票