线程同步辅助类

1:Semaphore

一个经典的信号量计数器。一般被用来控制对共享资源同时访问线程数量的控制。

 

特殊情况下信号量设置为1,那么就类似互斥锁的功能。

 

package cn.crxy.concurrent;

import java.sql.Time;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {
	public static void main(String[] args) {
		final Semaphore semaphore = new Semaphore(3);//信号量,解决了 允许固定个数的线程 同时访问共享资源
		for (int i = 0; i < 10; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						semaphore.acquire();// 获得许可
						System.out.println(Thread.currentThread().getName()+ ": 来了...现在有"+(3-semaphore.availablePermits())+"位顾客");
						TimeUnit.SECONDS.sleep(new Random().nextInt(5));
						System.out.println("-->"+Thread.currentThread().getName()+ ": 走了...");
						semaphore.release();// 释放许可
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
}

2:CountDownLatch

CountDownLatch 内部有个计数器,通过构造函数来指定。这个类就好比是倒计时的电子牌,当倒计时为0的时候就可以一起做一些事情。

package cn.crxy.concurrent;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/*
 * 一组线程,等待另一组线程。
 * 
 */
public class CountDownLatchDemo {

	public static void main(String[] args) throws InterruptedException {
		final CountDownLatch cdl = new CountDownLatch(1);
		final CountDownLatch cdl2 = new CountDownLatch(3);
		Thread t = new Thread(new Runnable() {// 裁判
					@Override
					public void run() {
						System.out.println("预备:");
						for (int i = 3; i >= 1; i--) {
							System.out.println(i + "...");
							try {
								TimeUnit.SECONDS.sleep(1);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						System.out.println("跑!");
						cdl.countDown(); // 计数器 减1
					}
				});
		t.start();
		// t.join();//插入
		// System.out.println("main:aaaaa");
		for (int i = 0; i < 3; i++) {// 运动员
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						cdl.await(); // 等待,知道计数器变为0 为止
						System.out.println(Thread.currentThread().getName()+ ":启动了...");
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						System.out.println("--》"+Thread.currentThread().getName()+ ":到达终点了...");
						cdl2.countDown();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					cdl2.await();
					System.out.println("宣布成绩!");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
}


3:CyclicBarrier

CyclicBarrier 一种可重置的多路同步点,在某些并发编程场景很有用。它允许一组线程互相等待,直到到达某个公共的屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier在释放等待线程后可以重用,所以称它为循环的barrier


package cn.crxy.concurrent;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

/*
 * 一组线程相互等待,直到最后一个线程执行完某一阶段任务后,他们才会一起向下执行。
 * 
 */
public class CyclicBarrierDemo {

	public static void main(String[] args) {
		final CyclicBarrier cb = new CyclicBarrier(3);
		System.out.println("出发...");
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						System.out.println(Thread.currentThread().getName()+":到达山顶了。。。");
						cb.await();
						System.out.println();
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						System.out.println(Thread.currentThread().getName()+":吃完饭了。。。");
						cb.await();
						System.out.println();
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						System.out.println(Thread.currentThread().getName()+":唱完歌了。。。");
						cb.await();
						System.out.println("回家");
					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (BrokenBarrierException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
}
4:Exchanger

Exchanger 允许两个线程在某个汇合点交换对象,在某些管道设计时比较有用。Exchanger提供了一个同步点,在这个同步点,一对线程可以交换数据。每个线程通过exchange()方法的入口提供数据给他的伙伴线程,并接收他的伙伴线程提供的数据并返回。当两个线程通过Exchanger交换了对象,这个交换对于两个线程来说都是安全的。Exchanger可以认为是 SynchronousQueue 的双向形式,在运用到遗传算法和管道设计的应用中比较有用。



package cn.crxy.concurrent;

import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;

public class ExchangeerDemo {

	public static void main(String[] args) {

		final Exchanger<String>  exchanger = new Exchanger<String>();
		
	//	for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + "卖包子。。。");
					try {
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						String s1 = "包子";
						String s2 = exchanger.exchange(s1);
						System.out.println(Thread.currentThread().getName()+":"+s2);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				}
			}).start();
	//	}
//		for (int i = 0; i < 3; i++) {

			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("-->"+Thread.currentThread().getName() + "买包子。。。");
					try {
						TimeUnit.SECONDS.sleep(new Random().nextInt(5)+1);
						String s1 = "100元";
						String s2 = exchanger.exchange(s1);
						System.out.println("-->"+Thread.currentThread().getName()+":"+s2);
						
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				}
			}).start();
	//	}


	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值