JAVA 多线程同步工具类总结



这两天看了《JAVA 并发编程实战》一书,内容很不错,关于同步常用的几个工具类总结如下:

  • CountDownLatch 闭锁:可以延迟线程的进度,直到锁到达终止状态。闭锁的作用相当于一扇门,在锁到达终止状态之前这扇门一直是关闭的。当锁到达终止状态时,允许所有线程通过。CountDownLatch 有一个初始值,通过调用 countDown 可以减少该值,一直到 0 时到达终止状态。

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

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

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

CountDownLatch 的例子:

  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. }  
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;


public class DemoOfLatch {

	// 利用闭锁 CountDownLatch 控制主线程和子线程的同步
	public static void main(String[] args) {
		
		int numberOfThread = 5;
		final CountDownLatch startLatch = new CountDownLatch(1);				// 用于控制子线程开始
		final CountDownLatch stopLatch = new CountDownLatch(numberOfThread);	// 用于子线程计数
		final AtomicInteger count = new AtomicInteger(0);						// 用于分配子线程唯一标识
		
		System.out.println("Main thread start...");
		
		for ( int i=0; i<numberOfThread; i++ ) {
			Thread thread = new Thread( new Runnable() {

				@Override
				public void run() {
					int tid = count.getAndIncrement();
					try {
						// 等代主线程打开启动信号
						startLatch.await();
						System.out.printf("Thread %d started...%n", tid);
						int duration = (int)(Math.random() * 5000);
						Thread.sleep(duration);
					} catch (InterruptedException e) {
						e.printStackTrace();
						Thread.currentThread().interrupt();
					} finally {
						System.out.printf("Thread %d stoped...%n", tid);
						// 线程终止前减少线程计数
						stopLatch.countDown();
					}
				}
				
			});
			thread.start();
		}
		
		// 在放行子线程之前做点什么别的事情
		System.out.println("Main thread do preparation work for child threads...");
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		// 打开闭锁放行所有子线程
		System.out.println("Main thread let child threads go...");
		startLatch.countDown();
		
		try {
			// 等待子线程计数降为 0 即所有子线程执行完毕
			System.out.println("Main thread wait for all child threads...");
			stopLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("Main thread exit...");
	}

}

FutureTask 的例子:

  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. }  
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


public class DemoOfFutureTask {

	public static void main(String[] args) {
		
		// 创建一个 Future Task 用于并发执行长任务
		final FutureTask<Movie> future = new FutureTask<Movie>( new Callable<Movie>() {

			@Override
			public Movie call() throws Exception {
				System.out.println("Future task started...");
				Thread.sleep(5000);
				System.out.println("Future task finished...");
				return new Movie("2012","Unknown");
			}
			
		});
		
		// 在子线程中启动任务
		Thread thread = new Thread(future);
		thread.start();
		
		// 主线程干点别的事情
		System.out.println("Now let's do sth eles...");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		// 主线程开始取结果
		System.out.println("Now wait for result of future task...");
		try {
			Movie res = future.get();
			System.out.printf("Result from task is name=%s, actor=%s", res.name, res.actor);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

	}
	
	public static class Movie {
		final public String name;
		final public String actor;
		public Movie(String name, String actor) {
			this.name = name;
			this.actor = actor;
		}
	}

}

Semaphore 的例子:

  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. }  
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class DemoOfSemaphore {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final int numOfThread = 5;
		final AtomicInteger count = new AtomicInteger(0);		// 用于分配唯一线程标识
		final Semaphore semaphore = new Semaphore(numOfThread); // 用于控制并发线程数目

		for (int i = 0; i < 10; i++) {
			Thread thread = new Thread(new Runnable() {

				@Override
				public void run() {
					int tid = count.getAndIncrement();
					try {
						// 等待直到取得信号量
						System.out.printf("Thread %d wait on semaphore...%n", tid);
						semaphore.acquire();
						// 取得信号量之后做点事情
						System.out.printf("Thread %d get semaphore...%n", tid);
						int duration = (int)(Math.random() * 5000);
						Thread.sleep(duration);
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						// 做完后释放信号量
						System.out.printf("Thread %d release semaphore...%n", tid);
						semaphore.release();
					}
					
				}
				
			});
			thread.start();
		}
		
	}

}

CyclicBarrier 的例子:

  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.   
  65. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值