All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.xiaoyuge5201.thread.SyncQueue Maven / Gradle / Ivy

There is a newer version: 1.3.5
Show newest version
package com.github.xiaoyuge5201.thread;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 同步队列
 * @author yugb
 * @param 
 */
public class SyncQueue {
	private static Logger logger = LoggerFactory.getLogger(SyncQueue.class);

	/*--------------------------私有属性 start-------------------------------*/
	/** 队列条目 */
	private final E[] items;
	/** 获取对象的游标 */
	private int takeIndex;
	/** 加入对象的游标 */
	private int putIndex;
	/** 条目数目 */
	private int count;
	/** 队列结束标记 */
	private boolean isClosed;

	/** 主锁 */
	private final ReentrantLock lock;
	/** 入队列的条件锁 */
	private final Condition putCondition;
	/** 出队列的条件锁 */
	private final Condition takeCondition;

	/*--------------------------私有属性 end-------------------------------*/

	/*--------------------------构造器 start-------------------------------*/
	@SuppressWarnings("unchecked")
	public SyncQueue(int capacity) {
		this.items = (E[]) new Object[capacity];
		lock = new ReentrantLock(false);
		takeCondition = lock.newCondition();
		putCondition = lock.newCondition();
	}

	/*--------------------------构造器 end-------------------------------*/

	/*--------------------------公有方法 start-------------------------------*/
	/**
	 * 入队列。若队列已满,则阻塞线程
	 * 
	 * @param item 项
	 * @return 是否成功插入
	 * @throws InterruptedException
	 * @throws NullPointerException item为空时,抛出此异常
	 */
	public boolean put(E item) throws InterruptedException {
		if (item == null)
			throw new NullPointerException();
		if (isClosed) {
			logger.warn("队列已经关闭,入队列失败!");
			return false;
		}
		lock.lockInterruptibly();
		try {
			try {
				while (count == items.length) {
					putCondition.await();
				}
			} catch (InterruptedException ie) {
				putCondition.signal();
				throw ie;
			}
			insert(item);
		} finally {
			lock.unlock();
		}
		return true;
	}

	/**
	 * 出队列。若队列空,阻塞队列
* 如果队列已经关闭,只有队列为空时才返回null * @return 项 * @throws InterruptedException */ public E take() throws InterruptedException { lock.lockInterruptibly(); try { try { while (count == 0) { if (isClosed) return null; takeCondition.await(); } } catch (InterruptedException ie) { takeCondition.signal(); throw ie; } return extract(); } finally { lock.unlock(); } } /** * 队列中的项数 * * @return 项数 */ public int size() { lock.lock(); try { return count; } finally { lock.unlock(); } } /** * 清空队列
* 清空队列后,会重新唤醒所有阻塞的put线程 */ public void clear() { lock.lock(); try { int i = takeIndex; int k = count; while (k-- > 0) { items[i] = null; i = inc(i); } count = 0; putIndex = 0; takeIndex = 0; isClosed = false; putCondition.signalAll(); } finally { lock.unlock(); } } /** * 唤醒所有出队列线程
* 此方法多用于当队列关闭且队列中数据已空时,唤醒被阻塞的出队列线程,使其退出或执行其他动作 */ public void signalAllTake() { lock.lock(); try { takeCondition.signalAll(); } finally { lock.unlock(); } } /** * 唤醒所有入队列线程
* 此方法多用于队列关闭且队列已满,而再没有任何线程调用take方法时,唤醒阻塞的入队列线程。 */ public void signalAllput() { lock.lock(); try { takeCondition.signalAll(); } finally { lock.unlock(); } } /** * 关闭队列
* 关闭队列后,仍然可以出队列直到队列为空,但是无法将数据入队列。当队列数据为空后,出队列数据为null
* 当关闭队列后,关闭标志将一直存在,除非执行clear()方法重置队列。 */ public void close() { this.isClosed = true; } /** * 队列是否已经关闭 * @return 是否已经关闭 */ public boolean isClosed() { return this.isClosed; } /*--------------------------公有方法 end-------------------------------*/ /*--------------------------私有方法 start-------------------------------*/ /** * 循环队列增,若增加值超出数组范围,则返回到第一个项 * * @param index 起始的位置 */ private final int inc(int index) { return (++index == items.length) ? 0 : index; } /** * 插入条目(项) * @param item 项 */ private void insert(E item) { items[putIndex] = item; putIndex = inc(putIndex); ++count; // 插入后唤醒等待take的线程 takeCondition.signal(); } /** * 提取条目(项) * @return 项 */ private E extract() { if (count == 0) return null; E x = items[takeIndex]; items[takeIndex] = null; takeIndex = inc(takeIndex); --count; // 提取后唤醒等待put的线程 putCondition.signal(); return x; } /*--------------------------私有方法 end-------------------------------*/ }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy