多线程中使用Condition实现等待/通知

时间:2020-12-29 21:13:20

多线程中使用Condition实现等待/通知

        关键字synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待/通知模式,类ReetranLock也可以实现同样的功能,但需要借助于Condition对象。Condition类是jdk5中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个condition(即对象监视器)实例,线程对象可以注册在指定的condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。

一.正确使用Condition实现等待/通知

新建MyService.java:

package service;

 

importjava.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

importjava.util.concurrent.locks.ReentrantLock;

 

public class MyService {

 

         privateLock lock = new ReentrantLock();

         publicCondition condition = lock.newCondition();

 

         publicvoid await() {

                   try{

                            lock.lock();

                            System.out.println("await时间为" +System.currentTimeMillis());

                            condition.await();

                   }catch (InterruptedException e) {

                            e.printStackTrace();

                   }finally {

                            lock.unlock();

                   }

         }

 

         publicvoid signal() {

                   try{

                            lock.lock();

                            System.out.println("signal时间为" + System.currentTimeMillis());

                            condition.signal();

                   }finally {

                            lock.unlock();

                   }

         }

}

类ThreadA.java:

 packageextthread;

 

import service.MyService;

 

public class ThreadA extends Thread {

 

         privateMyService service;

 

         publicThreadA(MyService service) {

                   super();

                   this.service= service;

         }

 

         @Override

         publicvoid run() {

                   service.await();

         }

}

类Run.java :

package test;

 

import service.MyService;

import extthread.ThreadA;

 

public class Run {

 

         publicstatic void main(String[] args) throws InterruptedException {

 

                   MyServiceservice = new MyService();

 

                   ThreadAa = new ThreadA(service);

                   a.start();

 

                   Thread.sleep(3000);

 

                   service.signal();

 

         }

 

}

程序运行结果如下:

   成功实现等待/通知模式。

  Object类中的wait方法相当于Conditon类中await()方法。

  Object类中的wait(long timeout)方法相当于Condition类中的await(longtime,TimeUnit unit)方法。

  Object类中的notify()方法相当于Condition类中的signal()方法。

  Object类中的notifyAll()方法相当于Condition类中的signalAll()方法。

二. 使用多个Condition实现通知部分线程

新建MyService.java :

package service;

 

importjava.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

importjava.util.concurrent.locks.ReentrantLock;

 

public class MyService {

 

         privateLock lock = new ReentrantLock();

         publicCondition conditionA = lock.newCondition();

         publicCondition conditionB = lock.newCondition();

 

         publicvoid awaitA() {

                   try{

                            lock.lock();

                            System.out.println("beginawaitA时间为" +System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                            conditionA.await();

                            System.out.println("  end awaitA时间为" + System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                   }catch (InterruptedException e) {

                            e.printStackTrace();

                   }finally {

                            lock.unlock();

                   }

         }

 

         publicvoid awaitB() {

                   try{

                            lock.lock();

                            System.out.println("beginawaitB时间为" +System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                            conditionB.await();

                            System.out.println("  end awaitB时间为" + System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                   }catch (InterruptedException e) {

                            e.printStackTrace();

                   }finally {

                            lock.unlock();

                   }

         }

 

         publicvoid signalAll_A() {

                   try{

                            lock.lock();

                            System.out.println("  signalAll_A时间为" + System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                            conditionA.signalAll();

                   }finally {

                            lock.unlock();

                   }

         }

 

         publicvoid signalAll_B() {

                   try{

                            lock.lock();

                            System.out.println("  signalAll_B时间为" + System.currentTimeMillis()

                                               +" ThreadName=" + Thread.currentThread().getName());

                            conditionB.signalAll();

                   }finally {

                            lock.unlock();

                   }

         }

新建ThreadA.java :

package extthread;

 

import service.MyService;

 

public class ThreadA extends Thread {

 

         privateMyService service;

 

         publicThreadA(MyService service) {

                   super();

                   this.service= service;

         }

 

         @Override

         publicvoid run() {

                   service.awaitA();

         }

}

新建ThreadB.java :

package extthread;

 

import service.MyService;

 

public class ThreadB extends Thread {

 

         privateMyService service;

 

         publicThreadB(MyService service) {

                   super();

                   this.service= service;

         }

 

         @Override

         publicvoid run() {

                   service.awaitB();

         }

}

新建Run.java :

package test;

 

import service.MyService;

import extthread.ThreadA;

import extthread.ThreadB;

 

public class Run {

 

         publicstatic void main(String[] args) throws InterruptedException {

 

                   MyServiceservice = new MyService();

 

                   ThreadAa = new ThreadA(service);

                   a.setName("A");

                   a.start();

 

                   ThreadBb = new ThreadB(service);

                   b.setName("B");

                   b.start();

 

                   Thread.sleep(3000);

 

                   service.signalAll_A();

         }

}

    运行结果如下,只有线程A被唤醒了:

    由此可见,使用ReetrantLock对象可以唤醒指定种类的线程,这是控制部分线程行为的的方便方式。