java常用同步工具类

阻塞队列:

BlockingQueue接口定义了可阻塞的put和take方法,同时也提供了非阻塞式的offer和poll方法。如果队列已满,那么put方法将阻塞直到有空间可用,如果队列为空那么take方法将会阻塞直到队列中有元素可以使用。而offer以及poll两个方法当队列已满或者队列为空而存储失败的时候,返回false。因此阻塞队列是利用队列的存储状态来控制线程的执行状态。

可以利用阻塞队列使用生产者——消费者模式,生产者把数据放入队列,而消费者从队列中读取数据,生产者不需要知道消费者的状态和数量,消费者同样不需要知道生产者是谁,只是从队列中读取数据进行使用。


 
 package com.pingan.home.demo;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

public class BlockQueueShow {

	static BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<Integer>();;

	public static void main(String[] args) {
		Thread product = new Thread(new BlockQueueCreate());
		Thread consumer = new Thread(new BlockQueueConsumer());
		product.start();
		consumer.start();
	}

}

class BlockQueueCreate implements Runnable {

	@Override
	public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				BlockQueueShow.blockingQueue.put(i);
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}

}

class BlockQueueConsumer implements Runnable {

	@Override
	public void run() {
		try {
			while (true) {
				System.out.println("Take:"+BlockQueueShow.blockingQueue.take());
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}

}


闭锁

闭锁可以延迟线程的进度直到其到达终止状态,闭锁相当于一扇门,初始状态为关闭的,没有任何线程可以通过,当满足一定的条件之后,闭锁这扇门会打开,允许所有的线程通过。闭锁可以确保某些任务知道其他的任务都完成之后才继续执行。
CountDownLatch是闭锁的一种实现,其状态包括一个计数器,该计数器在创建闭锁的时候被初始化为一个正整数,表示需要等待的事件数量。countDown方法用来改变闭锁的状态,调用一个闭锁的计数器就会递减,await方法会一直阻塞直到计数器变为0才开始执行。

 
package com.pingan.home.demo;

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

public class CountDownLatchShow {

	/* 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。 */
	public static void main(String[] args) throws InterruptedException {
		
		
		ExecutorService runners = Executors.newFixedThreadPool(10);
		/* 十名选手 */
		for (int i = 0; i < 10; i++) {
			Runner runner=new Runner();
			runners.submit(runner);
		}
		/* begin减一,开始游戏 */
		CountDownLatchUtil.begin.countDown();
		long beginTime = System.nanoTime();
		/* 等待end变为0,即所有选手到达终点 */
		CountDownLatchUtil.end.await();
		long lastEndTime = System.nanoTime();
		System.out.println(lastEndTime - beginTime);
		runners.shutdown();
	}

}
class CountDownLatchUtil{
	/* 开始的倒数锁 */
	final static CountDownLatch begin = new CountDownLatch(1);
	/* 结束的倒数锁 */
	final static CountDownLatch end = new CountDownLatch(10);
}
class Runner implements Runnable {

	@Override
	public void run() {

		try {
			System.out.println(Thread.currentThread().getName()+ ":准备好");
			long everyoneStartTime = System.nanoTime();
			/**
			 * 1.如果当前计数为零,则此方法立即返回,顺序执行下面代码。
			 * 2.等待(begin.countDown()代码后才会释放所有等待线程)
			 */
			CountDownLatchUtil.begin.await();
			Thread.sleep((long) (Math.random() * 1000));
			long everyoneEndTime = System.nanoTime();
			System.out.println(Thread.currentThread().getName()+ ":跑完"+ (everyoneEndTime - everyoneStartTime));
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			/* 每个选手到达终点时,end就减一 */
			CountDownLatchUtil.end.countDown();
		}
	}

}

信号量

计数信号量(Counting Semaphore)用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,计数信号量还可以用来实现某种资源池或者对容器施加边界。
Semaphore中管理者一组虚拟的许可,通过构造函数来进行初始化。在执行操作的时候可以首先获得许可(r如果还有剩余的许可),并在使用后释放许可,如果没有许可那么acquire方法将阻塞直到有许可。release方法将返回一个许可信号量。因此我们可用使用Semaphore将任何容器变成有界的阻塞容器。

package com.pingan.home.demo;

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

public class SemaphoreShow {

	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("Accessing: " + NO);
						Thread.sleep((long) (Math.random() * 10000));
						// 访问完后,释放 ,如果屏蔽下面的语句,则在控制台只能打印5条记录,之后线程一直阻塞
						semp.release();
					} catch (InterruptedException e) {
					}
				}
			};
			exec.execute(run);
		}
		// 退出线程池
		exec.shutdown();
	}
}


你可能感兴趣的:(java)