JAVA 多线程同步工具类总结

来源:互联网 发布:linux查看电池电量 编辑:程序博客网 时间:2024/06/15 07:04
关于同步常用的几个工具类总结如下:
  • CountDownLatch 闭锁:可以延迟线程的进度,直到锁到达终止状态。闭锁的作用相当于一扇门,在锁到达终止状态之前这扇门一直是关闭的。当锁到达终止状态时,允许所有线程通过。CountDownLatch 有一个初始值,通过调用 countDown 可以减少该值,一直到 0 时到达终止状态。

  • FutureTask 用于执行一个可返回结果的长任务,任务在单独的线程中执行,其他线程可以用 get 方法取任务结果,如果任务尚未完成,线程在 get 上阻塞。

  • Semaphore 用于控制同时访问某资源,或同时执行某操作的线程数目。信号量有一个初始值即可以分配的信号量总数目。线程任务开始前先调用 acquire 取得信号量,任务结束后调用 release 释放信号量。在 acquire 是如果没有可用信号量,线程将阻塞在 acquire 上,直到其他线程释放一个信号量。

  • CyclicBarrier 栅栏用于多个线程多次迭代时进行同步,在一轮任务中,任何线程完成任务后都在 barrier 上等待,直到所有其他线程也完成任务,然后一起释放,同时进入下一轮迭代。

CountDownLatch 的例子:

[java] view plain copy
  1. import java.util.concurrent.CountDownLatch;  
  2. import java.util.concurrent.atomic.AtomicInteger;  
  3.   
  4.   
  5. public class DemoOfLatch {  
  6.   
  7.     // 利用闭锁 CountDownLatch 控制主线程和子线程的同步  
  8.     public static void main(String[] args) {  
  9.           
  10.         int numberOfThread = 5;  
  11.         final CountDownLatch startLatch = new CountDownLatch(1);                // 用于控制子线程开始  
  12.         final CountDownLatch stopLatch = new CountDownLatch(numberOfThread);    // 用于子线程计数  
  13.         final AtomicInteger count = new AtomicInteger(0);                       // 用于分配子线程唯一标识  
  14.           
  15.         System.out.println("Main thread start...");  
  16.           
  17.         for ( int i=0; i<numberOfThread; i++ ) {  
  18.             Thread thread = new Thread( new Runnable() {  
  19.   
  20.                 @Override  
  21.                 public void run() {  
  22.                     int tid = count.getAndIncrement();  
  23.                     try {  
  24.                         // 等代主线程打开启动信号  
  25.                         startLatch.await();  
  26.                         System.out.printf("Thread %d started...%n", tid);  
  27.                         int duration = (int)(Math.random() * 5000);  
  28.                         Thread.sleep(duration);  
  29.                     } catch (InterruptedException e) {  
  30.                         e.printStackTrace();  
  31.                         Thread.currentThread().interrupt();  
  32.                     } finally {  
  33.                         System.out.printf("Thread %d stoped...%n", tid);  
  34.                         // 线程终止前减少线程计数  
  35.                         stopLatch.countDown();  
  36.                     }  
  37.                 }  
  38.                   
  39.             });  
  40.             thread.start();  
  41.         }  
  42.           
  43.         // 在放行子线程之前做点什么别的事情  
  44.         System.out.println("Main thread do preparation work for child threads...");  
  45.         try {  
  46.             Thread.sleep(2000);  
  47.         } catch (InterruptedException e) {  
  48.             e.printStackTrace();  
  49.         }  
  50.   
  51.         // 打开闭锁放行所有子线程  
  52.         System.out.println("Main thread let child threads go...");  
  53.         startLatch.countDown();  
  54.           
  55.         try {  
  56.             // 等待子线程计数降为 0 即所有子线程执行完毕  
  57.             System.out.println("Main thread wait for all child threads...");  
  58.             stopLatch.await();  
  59.         } catch (InterruptedException e) {  
  60.             e.printStackTrace();  
  61.         }  
  62.           
  63.         System.out.println("Main thread exit...");  
  64.     }  
  65.   
  66. }  

FutureTask 的例子:

[java] view plain copy
  1. import java.util.concurrent.Callable;  
  2. import java.util.concurrent.ExecutionException;  
  3. import java.util.concurrent.FutureTask;  
  4.   
  5.   
  6. public class DemoOfFutureTask {  
  7.   
  8.     public static void main(String[] args) {  
  9.           
  10.         // 创建一个 Future Task 用于并发执行长任务  
  11.         final FutureTask<Movie> future = new FutureTask<Movie>( new Callable<Movie>() {  
  12.   
  13.             @Override  
  14.             public Movie call() throws Exception {  
  15.                 System.out.println("Future task started...");  
  16.                 Thread.sleep(5000);  
  17.                 System.out.println("Future task finished...");  
  18.                 return new Movie("2012","Unknown");  
  19.             }  
  20.               
  21.         });  
  22.           
  23.         // 在子线程中启动任务  
  24.         Thread thread = new Thread(future);  
  25.         thread.start();  
  26.           
  27.         // 主线程干点别的事情  
  28.         System.out.println("Now let's do sth eles...");  
  29.         try {  
  30.             Thread.sleep(1000);  
  31.         } catch (InterruptedException e1) {  
  32.             e1.printStackTrace();  
  33.         }  
  34.           
  35.         // 主线程开始取结果  
  36.         System.out.println("Now wait for result of future task...");  
  37.         try {  
  38.             Movie res = future.get();  
  39.             System.out.printf("Result from task is name=%s, actor=%s", res.name, res.actor);  
  40.         } catch (InterruptedException e) {  
  41.             e.printStackTrace();  
  42.         } catch (ExecutionException e) {  
  43.             e.printStackTrace();  
  44.         }  
  45.   
  46.     }  
  47.       
  48.     public static class Movie {  
  49.         final public String name;  
  50.         final public String actor;  
  51.         public Movie(String name, String actor) {  
  52.             this.name = name;  
  53.             this.actor = actor;  
  54.         }  
  55.     }  
  56.   
  57. }  

Semaphore 的例子:

[java] view plain copy
  1. import java.util.concurrent.Semaphore;  
  2. import java.util.concurrent.atomic.AtomicInteger;  
  3.   
  4. public class DemoOfSemaphore {  
  5.   
  6.     /** 
  7.      * @param args 
  8.      */  
  9.     public static void main(String[] args) {  
  10.   
  11.         final int numOfThread = 5;  
  12.         final AtomicInteger count = new AtomicInteger(0);       // 用于分配唯一线程标识  
  13.         final Semaphore semaphore = new Semaphore(numOfThread); // 用于控制并发线程数目  
  14.   
  15.         for (int i = 0; i < 10; i++) {  
  16.             Thread thread = new Thread(new Runnable() {  
  17.   
  18.                 @Override  
  19.                 public void run() {  
  20.                     int tid = count.getAndIncrement();  
  21.                     try {  
  22.                         // 等待直到取得信号量  
  23.                         System.out.printf("Thread %d wait on semaphore...%n", tid);  
  24.                         semaphore.acquire();  
  25.                         // 取得信号量之后做点事情  
  26.                         System.out.printf("Thread %d get semaphore...%n", tid);  
  27.                         int duration = (int)(Math.random() * 5000);  
  28.                         Thread.sleep(duration);  
  29.                     } catch (InterruptedException e) {  
  30.                         e.printStackTrace();  
  31.                     } finally {  
  32.                         // 做完后释放信号量  
  33.                         System.out.printf("Thread %d release semaphore...%n", tid);  
  34.                         semaphore.release();  
  35.                     }  
  36.                       
  37.                 }  
  38.                   
  39.             });  
  40.             thread.start();  
  41.         }  
  42.           
  43.     }  
  44.   
  45. }  

CyclicBarrier 的例子:

[java] view plain copy
  1. import java.util.concurrent.BrokenBarrierException;  
  2. import java.util.concurrent.CyclicBarrier;  
  3.   
  4. public class DemoOfBarrier {  
  5.   
  6.     public static void main(String[] args) {  
  7.   
  8.         final int numOfThread = 2;  
  9.         final int numOfIteration = 2;  
  10.           
  11.         // 创建一个用于线程同步的 Barrier 对象  
  12.         final CyclicBarrier barrier = new CyclicBarrier(numOfThread,  
  13.                 new Runnable() {  
  14.   
  15.                     // 当所有线程到达 Barrier 后会执行这个任务  
  16.                     // 任务在第一个 到达 Barrier 的线程中执行  
  17.                     @Override  
  18.                     public void run() {  
  19.                         long tid = Thread.currentThread().getId();  
  20.                         // 当所有线程完成一轮迭代之后做点清除/准备/提交工作  
  21.                         System.out.printf("[%d] - All threads arrived barrier...%n", tid);  
  22.                         try {  
  23.                             Thread.sleep(2000);  
  24.                         } catch (InterruptedException e) {  
  25.                             e.printStackTrace();  
  26.                         }  
  27.                         System.out.printf("[%d] - Clear work done...%n", tid);  
  28.                     }  
  29.                       
  30.                 });  
  31.   
  32.         // 创建并启动多个线程,他们在 Barrier 上同步  
  33.         for (int i = 0; i < numOfThread; i++) {  
  34.             Thread thread = new Thread(new Runnable() {  
  35.   
  36.                 @Override  
  37.                 public void run() {  
  38.                     long tid = Thread.currentThread().getId();  
  39.                     for ( int k=0; k<numOfIteration; k++ ) {  
  40.                         try {  
  41.                             // 线程进行一轮迭代,做点事情  
  42.                             System.out.printf("Thread %d start its work...%n", tid);  
  43.                             long duration = (int)(Math.random()*5000);  
  44.                             Thread.sleep(duration);  
  45.                             // 做完迭代后等待其他线程完成迭代  
  46.                             System.out.printf("Thread %d wait on barrier...%n", tid);  
  47.                             int num = barrier.await();  
  48.                             // 显示完成的顺序  
  49.                             System.out.printf("Thread %d pass barrier with order=%d...%n", tid, num);  
  50.                         } catch (InterruptedException e) {  
  51.                             e.printStackTrace();  
  52.                             Thread.currentThread().interrupt();  
  53.                         } catch (BrokenBarrierException e) {  
  54.                             e.printStackTrace();  
  55.                         }  
  56.                     }  
  57.                 }  
  58.   
  59.             });  
  60.             thread.start();  
  61.         }  
  62.   
  63.     }  
  64.