并发工具类:CountDownLatch,Semaphore,CyclicBarrier,Exchanger简单使用

public class ConcurrentTest {
	private static int THREAD_COUNT=10;
	private static ExecutorService threadPool=Executors.newFixedThreadPool(THREAD_COUNT);
	


	public static void main(String[] args) {
		countDownLatchTest();
	}
	
	/**
	 * 1,CountDownLatch允许一个或多个线程等待其他线程完成操作,和Thread的join方法作用类似,是一个多线程同步工具。
	 * 2,调用CountDownLatch的countDown方法,计数器减1。await方法会阻塞当前线程,直到计数器变为0。
	 * 3,CountDownLatch不能重新初始化或者修改CountDownLatch对象内部计数器的值。
	 * 4,其他方法
	 * await(long time,TimeUnit unit),设置阻塞超时时间。超时后,当前线程不会再阻塞
	 * 
	 */
	static void countDownLatchTest(){
		//计数器的个数为THREAD_COUNT个
		CountDownLatch countDownLatch=new CountDownLatch(THREAD_COUNT);
		for( int i=0;i{
					countDownLatch.countDown();
					System.out.println(Thread.currentThread().getName());
			});
			
		}
		threadPool.shutdown();
		
		try {
			//调用await方法后,直到线程池中的所有线程执行结束,主线程才会继续执行。否则主线程阻塞等待
			countDownLatch.await();
			System.out.println("主线程");
		} catch (InterruptedException e) {
		}
	}
	
	/**
	 * 1,Semaphore(信号量) 用来控制同时访问特定资源的线程数量。可以用于做流量控制,特别是公用资源有限的资源场景。
	 * 2,下面的代码模拟只有5个数据库连接,但10个线程需要获取数据库连接保存数据的场景。 Semaphore设置为5,每个线程
	 * 先获取许可,如果获得了许可,则保存数据,保存之后释放该许可。没有许可可用时,线程阻塞。这样保证最多只有5个线程
	 * 同时运行
	 * 3,其他方法: 
	 * acquire(int permits):获取 permits 个许可;
	 * release(int permits):释放 permits 个许可
	 * boolean tryAcquire():尝试获取一个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
	 * boolean tryAcquire(long timeout, TimeUnit unit):尝试获取一个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false
	 * boolean tryAcquire(int permits):尝试获取 permits 个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
	 * boolean tryAcquire(int permits, long timeout, TimeUnit unit): 尝试获取 permits个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false个
	 * 
	 */
	static void semaphoreTest(){
		Semaphore semaphore=new Semaphore(5);
		for( int i=0;i{
				try {
					//获取一个许可;获取一个许可时,则许可数量减1.如果没有许可,则该方法阻塞,直到有许可 可用为止个
					semaphore.acquire();
					System.out.println(Thread.currentThread().getName()+"save data");
					//释放一个许可(释放之前必须先获取许可),许可数量加1
					semaphore.release();
				} catch (InterruptedException e) {
					e.printStackTrace();
			}
			});
		}
		
		threadPool.shutdown();
	}
	
	/**
	 * 1,CyclicBarrier字面意思为“可循环使用的屏障”,它要做的是:让一组线程达到一个屏障(也称之为同步点)时被阻塞,直到
	 * 最后一个线程到达屏障时,屏障才会放开,所有的线程才会继续执行。
	 * 2,CyclicBarrier可以用于多线程计算数据,最后合并计算结果的场景。
	 * 3,默认的构造方法是:CyclicBarrier(int parties),其参数表示屏障拦截线程的数量,每个线程调用await方法表示已经
	 * 到达了屏障,然后当前线程被阻塞。当第parties个线程到达屏障时,屏障才会放开、
	 * 4,常用的构造方法是CyclicBarrier(int parties,Runnable runnable),用于屏障被放开时,优先执行runnable方法。
	 */
	static void cyclicBarrierTest(){
		//模拟统计excel中每个sheet中数据的求和,然后汇总所有sheet的求和结果。每个sheet的求和使用一个单独的线程,
		 //汇总使用一个单独的线程,使用ConcurrentHashMap保存每个sheet的求和结果。
		ConcurrentHashMap sheetBankWaterSum=new ConcurrentHashMap();
		CyclicBarrier cyclicBarrier=new CyclicBarrier(THREAD_COUNT,new MyRunnable(sheetBankWaterSum));
		for( int i=0;i{
				try {
					//使用随机数模拟每个sheet的求和结果
					int itemSum=new Random().nextInt(10);
					sheetBankWaterSum.put(Thread.currentThread().getName(), itemSum);
					
					System.out.println(Thread.currentThread().getName()+"求和结果为:"+itemSum);
					//当前线程阻塞等待,直到第parties个线程到达屏障。
					cyclicBarrier.await();
					
				} catch (Exception e) {
					e.printStackTrace();
			}
			});
		}
		
		threadPool.shutdown();
		
	}
	
	/**
	 * 1,Exchanger(交换者)是一个用于线程间交换数据的工具类。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。
	 * 两个线程通过exchange方法交换数据,如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange方法,
	 * 两个线程都到达同步点时,就可以交换数据。
	 * 2,执行结果:
	 * t1线程获取到的数据是:t2的问候
	 * t2线程获取到的数据是:t1的问候
	 */
	static void exchangerTest(){
		Exchanger exchanger=new Exchanger<>();
		Thread t1=new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					String result=exchanger.exchange("t1的问候");
					System.out.println("t1线程获取到的数据是:"+result);
				} catch (InterruptedException e) {
				}
				
			}
		},"t1");
		
		Thread t2=new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					String result=exchanger.exchange("t2的问候");
					System.out.println("t2线程获取到的数据是:"+result);
				} catch (InterruptedException e) {
				}
				
			}
		},"t2");
		
		t1.start();
		t2.start();
	
		
	}
}
 class  MyRunnable implements Runnable{
	 private ConcurrentHashMap map;
	public MyRunnable(ConcurrentHashMap map) {
		super();
		this.map = map;
	}


	@Override
	public void run() {
		int result=0;
		for(Entry sheet:map.entrySet()){
			result+=sheet.getValue();
		}
		
		/**
		 * 打印的结果
		 * pool-1-thread-3求和结果为:4
			pool-1-thread-4求和结果为:8
			pool-1-thread-1求和结果为:2
			pool-1-thread-5求和结果为:7
			pool-1-thread-7求和结果为:2
			pool-1-thread-6求和结果为:4
			pool-1-thread-9求和结果为:4
			pool-1-thread-8求和结果为:1
			pool-1-thread-10求和结果为:3
			pool-1-thread-2求和结果为:3
			所有sheet求和结果:38
		 */
		System.out.println("所有sheet求和结果:"+result);
	}
 }

 

你可能感兴趣的:(java,并发编程,多线程,thread,数据库)