java并发编程之同步器

同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作。最常用的同步器是CountDownLatch和Semaphore,不常用的是Barrier 和Exchanger

倒计数器 锁存器是一次性障碍,允许一个或者多个线程等待一个或者多个其它线程来做某些事情。CountDownLatch的唯一构造器带一个int类型的参数,这个int参数是指允许所有在等待线程被处理之前,必须在锁存器上调用countDown方法的次数。

EG:

 

[java]   view plain copy print ?
  1. package hb.java.thread;  
  2.   
  3. import java.util.concurrent.CountDownLatch;  
  4.   
  5. /** 
  6.  *  
  7.  * @author hb 
  8.  *         CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0 
  9.  *         ,就只有阻塞等待了。 *JAVA同步器之 
  10.  *         CountDownLatch(不能循环使用,如果需要循环使用可以考虑使用CyclicBarrier) 两种比较常规用法: 1:new 
  11.  *         CountDownLatch(1);所有的线程在开始工作前需要做一些准备工作,当所有的线程都准备到位后再统一执行时有用 2:new 
  12.  *         CountDownLatch(THREAD_COUNT);当所有的线程都执行完毕后,等待这些线程的其他线程才开始继续执行时有用 
  13.  */  
  14. public class CountDownLatchTest {  
  15.     private static final int THREAD_COUNT = 10;  
  16.     // 在调用startSingal.countDown()之前调用了startSingal.await()的线程一律等待,直到startSingal.countDown()的调用  
  17.     private static final CountDownLatch startSingal = new CountDownLatch(1);  
  18.     // 在finishedSingal的初始化记数量通过调用finishedSingal.countDown()减少为0时调用了finishedSingal.await()的线程一直阻塞  
  19.     private static final CountDownLatch finishedSingal = new CountDownLatch(  
  20.             THREAD_COUNT);  
  21.   
  22.     public static void main(String[] args) throws InterruptedException {  
  23.         for (int i = 0; i < THREAD_COUNT; i++) {  
  24.             new Thread("Task " + i) {  
  25.                 public void run() {  
  26.                     System.out.println(Thread.currentThread().getName()  
  27.                             + " prepared!!");  
  28.                     try {  
  29.                         startSingal.await();  
  30.                     } catch (InterruptedException e) {  
  31.                         e.printStackTrace();  
  32.                     }  
  33.                     System.out.println(Thread.currentThread().getName()  
  34.                             + " finished!!");  
  35.                     finishedSingal.countDown();  
  36.                 };  
  37.             }.start();  
  38.         }  
  39.         Thread.sleep(1000);  
  40.         startSingal.countDown();// 所有的线程被唤醒,同时开始工作.countDown 方法的线程等到计数到达零时才继续  
  41.         finishedSingal.await();// 等待所有的线程完成!!  
  42.         System.out.println("All task are finished!!");  
  43.     }  
  44. }  

 

[java]   view plain copy print ?
  1. package hb.java.thread;  
  2.   
  3. import java.util.concurrent.BrokenBarrierException;  
  4. import java.util.concurrent.CyclicBarrier;  
  5.   
  6. /** 
  7.  *  
  8.  * JAVA同步器之Barrier(能够循环使用,当计数器增加到Barrier的初始化计数器之后马上会被置为0为下一次循环使用做准备) 
  9.  * Barrier能够为指定的一个或多个(一般为多个)线程设置一道屏障,只有当所有的线程都到达该屏障后才能一起冲过该屏障继续其他任务 一般可以new 
  10.  * CyclicBarrier(ThreadCount)来进行初始化,也可以new 
  11.  * CyclicBarrier(ThreadCount,RunableAction)当初始化数量的线程都调用 
  12.  * 了await()方法后触发RunableAction线程,也可以通过初始化一个new 
  13.  * CyclicBarrier(ThreadCount+1)的Barrier在前置线程未执行完成时一直阻塞一个或多个 
  14.  * 后续线程,这一点类似于CountDownLatch 
  15.  */  
  16. public class BarrierTest {  
  17.     private static final int THREAD_COUNT = 10;  
  18.     private static final CyclicBarrier barrier = new CyclicBarrier(  
  19.             THREAD_COUNT + 1new Runnable() {  
  20.   
  21.                 @Override  
  22.                 public void run() {  
  23.                     System.out.println("All task are prepared or finished!!");  
  24.                 }  
  25.             });  
  26.   
  27.     public static void main(String[] args) throws InterruptedException,  
  28.             BrokenBarrierException {  
  29.         for (int i = 0; i < THREAD_COUNT; i++) {  
  30.             new Thread("Task " + i) {  
  31.                 public void run() {  
  32.                     try {  
  33.                         System.out.println(Thread.currentThread().getName()  
  34.                                 + " prepared!!");  
  35.                         barrier.await();  
  36.                     } catch (InterruptedException e) {  
  37.                         // TODO Auto-generated catch block  
  38.                         e.printStackTrace();  
  39.                     } catch (BrokenBarrierException e) {  
  40.                         // TODO Auto-generated catch block  
  41.                         e.printStackTrace();  
  42.                     }  
  43.                     // do something  
  44.                     System.out.println(Thread.currentThread().getName()  
  45.                             + " finished!!");  
  46.                 };  
  47.             }.start();  
  48.         }  
  49.         barrier.await();  
  50.         // --------------开始准备循环使用--------------  
  51.         for (int i = 0; i < THREAD_COUNT; i++) {  
  52.             new Thread("Task " + i) {  
  53.                 public void run() {  
  54.   
  55.                     // do something  
  56.                     System.out.println(Thread.currentThread().getName()  
  57.                             + " finished!!");  
  58.                     try {  
  59.                         barrier.await();  
  60.                     } catch (InterruptedException e) {  
  61.                         // TODO Auto-generated catch block  
  62.                         e.printStackTrace();  
  63.                     } catch (BrokenBarrierException e) {  
  64.                         // TODO Auto-generated catch block  
  65.                         e.printStackTrace();  
  66.                     }  
  67.                 };  
  68.             }.start();  
  69.         }  
  70.         barrier.await();  
  71.     }  
  72. }  

 

[java]   view plain copy print ?
  1. package hb.java.thread;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.concurrent.Exchanger;  
  6.   
  7. public class ExchangerTest {  
  8.     final static Exchanger<List<String>> exchanger = new Exchanger<List<String>>();  
  9.   
  10.     public static void main(String[] args) {  
  11.         new Producer("Producer", exchanger).start();  
  12.         new Consumer("Consumer", exchanger).start();  
  13.     }  
  14.   
  15.     static class Producer extends Thread {  
  16.         private Exchanger<List<String>> exchanger;  
  17.   
  18.         /**  
  19.          *   
  20.          */  
  21.         public Producer(String threadName, Exchanger<List<String>> exchanger) {  
  22.             super(threadName);  
  23.             this.exchanger = exchanger;  
  24.         }  
  25.   
  26.         /* 
  27.          * (non-Javadoc) 
  28.          *  
  29.          * @see java.lang.Thread#run() 
  30.          */  
  31.         @Override  
  32.         public void run() {  
  33.             List<String> products = new ArrayList<String>();  
  34.             for (int i = 0; i < 10; i++) {  
  35.                 products.add("product " + i);  
  36.             }  
  37.             try {  
  38.                 List<String> results = exchanger.exchange(products);  
  39.                 System.out.println("get results from consumer");  
  40.                 for (String s : results) {  
  41.                     System.out.println(s);  
  42.                 }  
  43.             } catch (InterruptedException e) {  
  44.                 // TODO Auto-generated catch block  
  45.                 e.printStackTrace();  
  46.             }  
  47.         }  
  48.     }  
  49.   
  50.     static class Consumer extends Thread {  
  51.         private Exchanger<List<String>> exchanger;  
  52.   
  53.         /**  
  54.          *   
  55.          */  
  56.         public Consumer(String threadName, Exchanger<List<String>> exchanger) {  
  57.             super(threadName);  
  58.             this.exchanger = exchanger;  
  59.         }  
  60.   
  61.         /* 
  62.          * (non-Javadoc) 
  63.          *  
  64.          * @see java.lang.Thread#run() 
  65.          */  
  66.         @Override  
  67.         public void run() {  
  68.             List<String> products = new ArrayList<String>();  
  69.             for (int i = 0; i < 10; i++) {  
  70.                 products.add("consumed " + i);  
  71.             }  
  72.             try {  
  73.                 List<String> results = exchanger.exchange(products);  
  74.                 System.out.println("got products from produces");  
  75.                 for (String s : results) {  
  76.                     System.out.println(s);  
  77.                 }  
  78.             } catch (InterruptedException e) {  
  79.                 // TODO Auto-generated catch block  
  80.                 e.printStackTrace();  
  81.             }  
  82.         }  
  83.     }  
  84. }  
<!--StartFragment -->
当使用线程池,并发任务返回future集合时,如果任务有超时设置。可以使用countDownLatch来判断返回集合是否完成,如果线程任务会出现卡死的情况,使用future的超时返回方法获取返回结果。

 

 

你可能感兴趣的:(java并发编程之同步器)