1.线程中的wait()方法与sleep()方法
- 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
- sleep()方法只是让出了CPU,并不会释放资源锁。wait会释放锁,暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。
- sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用。
2.线程中的wait()方法与notify()方法
- 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的优势:时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票