Java并发编程:同步工具类

Java并发编程:同步工具类

1.Semaphore类  一个计数信号量,通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。功能和锁有点类似,它一般用于控制对某组资源的访问权限。

          acquire()用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可。

          release()用来释放许可。注意,在释放许可之前,必须先获获得许可。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final Semaphore sp = new Semaphore(3);

		for (int i = 0; i < 10; i++) {
			Runnable runnable = new Runnable() {
				public void run() {
					try {
						sp.acquire();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("线程 " + Thread.currentThread().getName()
							+ " 进入,当前已有 " + (3 - sp.availablePermits())
							+ "个线程并发");

					try {
						Thread.sleep((long) Math.random() * 1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("线程 " + Thread.currentThread().getName()
							+ "即将离开");
					sp.release();

					System.out.println("线程 " + Thread.currentThread().getName()
							+ " 已离开,当前已有" + (3 - sp.availablePermits())
							+ "个线程并发");
				}
			};
			service.execute(runnable);
		}
	}

}

 2.CyclicBarrier类一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。

一组线程等待至某个状态之后再全部同时执行,例如班级出外郊游,当所有人到齐后才出发到下一个目的地。

/*
 		集齐够了所有线程再进行下一步工作
 */
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final CyclicBarrier cb = new CyclicBarrier(3);
		for (int i = 0; i < 3; i++) {
			Runnable runnable = new Runnable() {
				public void run() {
					try {
						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ " 即将到达集合地点1,当前已有 "
								+ (cb.getNumberWaiting() + 1)
								+ "个已经到达,"
								+ ((cb.getNumberWaiting() == 2) ? " 全员都到齐了,出发!"
										: "正在等候"));
						cb.await();

						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ " 即将到达集合地点2,当前已有 "
								+ (cb.getNumberWaiting() + 1)
								+ "个已经到达,"
								+ ((cb.getNumberWaiting() == 2) ? "全员都到齐了,出发!"
										: "正在等候"));
						cb.await();
						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ " 即将到达集合地点3,当前已有 "
								+ (cb.getNumberWaiting() + 1)
								+ "个已经到达,"
								+ ((cb.getNumberWaiting() == 2) ? "全员都到齐了,返程!"
										: "正在等候"));
						cb.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			service.execute(runnable);
		}
		service.shutdown();
	}
}

 3.CountDownLatch类一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

CountDownLatch 使用一个计数器来实现,它初始化为一个正,用来表示需要等待的活动事件数。countDown 方法使计数器减一,表示一个事件已经发生了,而await方法等待计数器达到零,此时表示所有需要等待的事件都已发生,只有当计数器到达零时,锁才会开起。如果计数器的初始值不为零,await会一直阻塞直到计数器为零,或者是等待线程中断或超时。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountdownLatchTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final CountDownLatch cdOrder = new CountDownLatch(1); // 裁判吹一声口哨
																// 将计数1初始化做一个开/关锁存器,调用countDown()的线程打开
		final CountDownLatch cdAnswer = new CountDownLatch(3); // 三个运动员参加比赛
		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();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			service.execute(runnable);
		}
		try {
			Thread.sleep((long) (Math.random() * 10000));

			System.out.println("裁判" + Thread.currentThread().getName()
					+ "即将发布命令");
			cdOrder.countDown();
			System.out.println("裁判" + Thread.currentThread().getName()
					+ "已发送开始命令,正在等待比赛结果....");
			cdAnswer.await();
			System.out.println("裁判" + Thread.currentThread().getName()
					+ "已收到所有响应结果,宣布结果");
		} catch (Exception e) {
			e.printStackTrace();
		}
		service.shutdown();

	}
}

 4.Exchanger类   两个线程可以交换对象的同步点。每个线程都在进入 exchange 方法时给出某个对象,相互接受对方准备的对象。

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final Exchanger exchanger = new Exchanger();

		service.execute(new Runnable() {
			public void run() {
				try {
					Thread.sleep((long) (Math.random() * 10000));
					String data1 = "Drug";
					System.out.println("线程" + Thread.currentThread().getName()
							+ "正在把 " + data1 + " 换出去");
					String data2 = (String) exchanger.exchange(data1);
					System.out.println("线程" + Thread.currentThread().getName()
							+ "换回的东西为 " + data2);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		service.execute(new Runnable() {
			public void run() {
				try {
					Thread.sleep((long) (Math.random() * 10000));
					String data1 = "Money";
					System.out.println("线程" + Thread.currentThread().getName()
							+ "正在把 " + data1 + " 换出去");
					String data2 = (String) exchanger.exchange(data1);
					System.out.println("线程" + Thread.currentThread().getName()
							+ "换回的东西为" + data2);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
}

 

猜你喜欢

转载自lucas0802.iteye.com/blog/2213715