实现BlockingQueue

看了下JDK的源代码实现,模拟了一下ArrayBlockQueue,代码如下:

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

public class BlockQueue {
	private List<Integer> list;
	private int size;
	private final ReentrantLock lock;
	private final Condition isEmpty;
	private final Condition isFull;

	public BlockQueue(int size) {
		this.size = size;
		list = new LinkedList<Integer>();
		lock = new ReentrantLock();
		isEmpty = lock.newCondition();
		isFull = lock.newCondition();
	}

	public void put(int data) throws InterruptedException {
		final ReentrantLock lock = this.lock;
		lock.lockInterruptibly();
		try {
			while (list.size() == size) {
				try {
					isFull.await();
				} catch (InterruptedException e) {
					isFull.signal();
					throw e;
				}
			}
			list.add(data);
			System.out.println("size : " + list.size() + ", " + Thread.currentThread().getName() + " put " + data);
			isEmpty.signal();
		} finally {
			lock.unlock();
		}
	}

	public int take() throws InterruptedException {
		lock.lockInterruptibly();
		try {
			while (list.size() == 0) {
				try {
					isEmpty.await();
				} catch (InterruptedException e) {
					isEmpty.signal();
					throw e;
				}
			}
			int data = list.remove(0);
			System.out.println("size : " + list.size() + ", " + Thread.currentThread().getName() + " get " + data);
			isFull.signal();

			return data;
		} finally {
			lock.unlock();
		}
	}
}

import java.util.Random;

public class Producer implements Runnable {

	private BlockQueue bq;
	private String name;

	public Producer(String name, BlockQueue bq) {
		this.name = name;
		this.bq = bq;
	}

	@Override
	public void run() {
		Random ran = new Random();
		for(int i = 0; i < 10; i++){
			int data = ran.nextInt(20);
			try {
				bq.put(data);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//System.out.println(name + " put " + data);
		}
	}
}

public class Consumer implements Runnable {
	private BlockQueue bq;
	private String name;

	public Consumer(String name, BlockQueue bq) {
		this.bq = bq;
		this.name = name;
	}

	@Override
	public void run() {
		for(int i = 0; i < 10; i++){
			int data;
			try {
				data = bq.take();
				//System.out.println(name + " get " + data);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

import org.junit.Test;

public class BlockQueueTest {

	@Test
	public void test() throws InterruptedException {
		BlockQueue bq = new BlockQueue(5);

		Producer p1 = new Producer("producer 1", bq);
		Producer p2 = new Producer("producer 2", bq);
		Producer p3 = new Producer("producer 3", bq);
		Consumer c1 = new Consumer("consumer 1", bq);
		Consumer c2 = new Consumer("consumer 2", bq);
		Consumer c3 = new Consumer("consumer 3", bq);
		
		new Thread(p1).start();
		new Thread(p2).start();
		new Thread(p3).start();
		new Thread(c1).start();
		new Thread(c2).start();
		new Thread(c3).start();
		
		Thread.sleep(10000);
	}
}

运行结果如下:

size : 1, Thread-0 put 15
size : 2, Thread-0 put 0
size : 3, Thread-0 put 18
size : 4, Thread-0 put 9
size : 5, Thread-0 put 6
size : 4, Thread-3 get 15
size : 3, Thread-5 get 0
size : 2, Thread-5 get 18
size : 1, Thread-5 get 9
size : 0, Thread-5 get 6
size : 1, Thread-1 put 12
size : 0, Thread-4 get 12
size : 1, Thread-0 put 3
size : 2, Thread-2 put 2
size : 3, Thread-2 put 13
size : 4, Thread-2 put 12
size : 5, Thread-2 put 14
size : 4, Thread-5 get 3
size : 3, Thread-5 get 2
size : 2, Thread-5 get 13
size : 1, Thread-5 get 12
size : 0, Thread-5 get 14
size : 1, Thread-1 put 0
size : 2, Thread-1 put 3
size : 3, Thread-1 put 19
size : 4, Thread-1 put 13
size : 5, Thread-1 put 2
size : 4, Thread-4 get 0
size : 3, Thread-4 get 3
size : 2, Thread-4 get 19
size : 1, Thread-4 get 13
size : 0, Thread-4 get 2
size : 1, Thread-2 put 1
size : 2, Thread-2 put 9
size : 3, Thread-2 put 10
size : 4, Thread-2 put 14
size : 5, Thread-2 put 3
size : 4, Thread-5 get 1
size : 3, Thread-3 get 9
size : 2, Thread-3 get 10
size : 1, Thread-3 get 14
size : 0, Thread-3 get 3
size : 1, Thread-1 put 17
size : 2, Thread-1 put 14
size : 3, Thread-1 put 1
size : 4, Thread-1 put 10
size : 3, Thread-4 get 17
size : 2, Thread-4 get 14
size : 1, Thread-4 get 1
size : 0, Thread-4 get 10
size : 1, Thread-2 put 6
size : 2, Thread-0 put 1
size : 3, Thread-0 put 14
size : 4, Thread-0 put 9
size : 5, Thread-0 put 4
size : 4, Thread-3 get 6
size : 3, Thread-3 get 1
size : 2, Thread-3 get 14
size : 1, Thread-3 get 9
size : 0, Thread-3 get 4

说明:在Producer和Consumer线程里面打印语句的显示结果很令人迷惑,改成在BlockQueue里面打印就好了。


猜你喜欢

转载自fuxichakan.iteye.com/blog/1666061
今日推荐