import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * * 保护一个重要(代码)部分防止一次超过 N 个线程进入。 在N 个线程之间发送信号。 * @author fansxnet * */ public class SemaphoreTest { public static void main(String[] args) { // 线程池 ExecutorService exec = Executors.newCachedThreadPool(); // 只能5个线程同时访问 final Semaphore semp = new Semaphore(5); // 模拟20个客户端访问 for (int index = 0; index < 20; index++) { final int NO = index; Runnable run = new Runnable() { public void run() { try { // 获取许可 semp.acquire(); System.out.println(System.currentTimeMillis()+":Accessing: " + NO); Thread.sleep((long) (Math.random() * 10000)); // 访问完后,释放 ,如果屏蔽下面的语句,则在控制台只能打印5条记录,之后线程一直阻塞 semp.release(); } catch (InterruptedException e) { } } }; exec.execute(run); } // 退出线程池 exec.shutdown(); } }
1489915492740:Accessing: 0
1489915492746:Accessing: 1
1489915492748:Accessing: 2
1489915492749:Accessing: 3
1489915492749:Accessing: 4
1489915493792:Accessing: 5
1489915495852:Accessing: 6
1489915497145:Accessing: 8
1489915497299:Accessing: 7
1489915497681:Accessing: 9
1489915499427:Accessing: 10
1489915501457:Accessing: 11
1489915503579:Accessing: 12
1489915503953:Accessing: 13
1489915504278:Accessing: 14
1489915504941:Accessing: 15
1489915505704:Accessing: 16
1489915506731:Accessing: 17
1489915507014:Accessing: 18
1489915507420:Accessing: 19
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。 * @author fansxnet 该程序用来模拟发送命令与执行命令,主线程代表指挥官,新建3个线程代表战士,战士一直等待着指挥官下达命令, * 若指挥官没有下达命令,则战士们都必须等待。一旦命令下达,战士们都去执行自己的任务,指挥官处于等待状态,战士们任务执行完毕则报告给 * 指挥官,指挥官则结束等待。 */ public class CountdownLatchTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); // 创建一个线程池 final CountDownLatch cdOrder = new CountDownLatch(1);// 指挥官的命令,设置为1,指挥官一下达命令,则cutDown,变为0,战士们执行任务 final CountDownLatch cdAnswer = new CountDownLatch(3);// 因为有三个战士,所以初始值为3,每一个战士执行任务完毕则cutDown一次,当三个都执行完毕,变为0,则指挥官停止等待。 for (int i = 0; i < 3; i++) { Runnable runnable = new Runnable() { public void run() { try { System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令"); cdOrder.await(); // 战士们都处于等待命令状态 System.out.println("线程" + Thread.currentThread().getName() + "已接受命令"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果"); cdAnswer.countDown(); // 任务执行完毕,返回给指挥官,cdAnswer减1。 } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable);// 为线程池添加任务 } try { Thread.sleep((long) (Math.random() * 10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令"); cdOrder.countDown(); // 发送命令,cdOrder减1,处于等待的战士们停止等待转去执行任务。 System.out.println("线程" + Thread.currentThread().getName() + "已发送命令,正在等待结果"); cdAnswer.await(); // 命令发送后指挥官处于等待状态,一旦cdAnswer为0时停止等待继续往下执行 System.out.println("线程" + Thread.currentThread().getName() + "已收到所有响应结果"); } catch (Exception e) { e.printStackTrace(); } service.shutdown(); // 任务结束,停止线程池的所有线程 } }
线程pool-1-thread-1正准备接受命令
线程pool-1-thread-2正准备接受命令
线程pool-1-thread-3正准备接受命令
线程main即将发布命令
线程main已发送命令,正在等待结果
线程pool-1-thread-1已接受命令
线程pool-1-thread-2已接受命令
线程pool-1-thread-3已接受命令
线程pool-1-thread-1回应命令处理结果
线程pool-1-thread-2回应命令处理结果
线程pool-1-thread-3回应命令处理结果
线程main已收到所有响应结果
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。 * 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。 * 在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。 因为该 barrier * * 在释放等待线程后可以重用,所以称它为循环 的 barrier。 * 需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用CyclicBarrier。 * * @author fansxnet * */ public class CyclicBarrierTest { private static final int STUDENT_NUM = 10; public static void main(String[] args) { // TODO Auto-generated method stub Runnable teacher = new Runnable() { // 当所有线程到达barrier时执行 public void run() { System.out.println("同学们,咱们出发"); } }; final CyclicBarrier cb = new CyclicBarrier(STUDENT_NUM, teacher); ExecutorService executor = Executors.newFixedThreadPool(STUDENT_NUM); for (int i = 0; i < STUDENT_NUM; i++) { final int studentId = i; executor.submit(new Runnable() { public void run() { // TODO Auto-generated method stub try { System.out.println("学生:" + studentId + " 等待"); // 线程在这里等待,直到所有线程都到达barrier。 cb.await(); System.out.println("学生:" + studentId + " 出发"); } catch (Exception e) { e.printStackTrace(); } } }); } } }
学生:1 等待
学生:0 等待
学生:2 等待
学生:3 等待
学生:4 等待
学生:5 等待
学生:6 等待
学生:7 等待
学生:8 等待
学生:9 等待
同学们,咱们出发
学生:9 出发
学生:1 出发
学生:4 出发
学生:3 出发
学生:2 出发
学生:0 出发
学生:8 出发
学生:7 出发
学生:6 出发
学生:5 出发
看看 http://blog.csdn.net/defonds/article/details/44021605/