juc之CountDownLatch、CyclicBarrier和Semaphore例子

 

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/

猜你喜欢

转载自xiaofancn.iteye.com/blog/2364012