基于多线程编程实现一个生产者消费者模型
方法一:使用Object的wait和notify
代码如下
java
private static Object object = new Object();
private static int SIZE = 10;
private static LinkedList<Integer> list = new LinkedList<>();
private static volatile boolean flag = true;
@Test
public void testCase01() {
ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
private volatile int index = 0;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "t" + (index++));
}
});
for (int i = 0; i < 5; i++) {
threadPool.submit(new Producer());
threadPool.submit(new Consumer());
}
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
threadPool.shutdown();
}
private static class Producer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
synchronized (object) {
if (list.size() >= SIZE) {
object.notifyAll();
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is full " +
" size=" + list.size());
} else {
int num = new Random().nextInt(100);
list.addLast(num);
System.out.println(Thread.currentThread().getName() + " add num=" + num +
" size=" + list.size());
object.notifyAll();
}
}
}
}
}
private static class Consumer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
synchronized (object) {
if (list.size() <= 0) {
object.notifyAll();
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is full " +
" size=" + list.size());
} else {
int num = list.removeFirst();
System.out.println(Thread.currentThread().getName() + " remove num=" + num +
" size=" + list.size());
object.notifyAll();
}
}
}
}
}
运行结果
ini
t6 add num=9 size=1
t2 add num=2 size=2
t0 add num=31 size=3
t3 remove num=9 size=2
t1 remove num=2 size=1
t7 remove num=31 size=0
t4 add num=13 size=1
t8 add num=9 size=2
方法2:基于阻塞队列实现
代码实现
java
private static int SIZE = 2;
private static BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>(SIZE);
private static volatile boolean flag = true;
private static AtomicInteger curSize = new AtomicInteger(0);
@Test
public void testCase01() {
ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
private volatile int index = 0;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "t" + (index++));
}
});
for (int i = 0; i < 5; i++) {
threadPool.submit(new Producer());
threadPool.submit(new Consumer());
}
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
threadPool.shutdown();
}
private static class Producer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
int num = new Random().nextInt(100);
try {
blockingDeque.put(num);
System.out.println(Thread.currentThread().getName() + " add num=" + num +
" size=" + curSize.addAndGet(1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class Consumer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
try {
int num = blockingDeque.take();
System.out.println(Thread.currentThread().getName() + " remove num=" + num +
" size=" + curSize.addAndGet(-1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
打印结果
打印结果因为多线程导致是乱序的
ini
t8 add num=24 size=1
t3 remove num=70 size=0
t7 remove num=76 size=1
t0 add num=70 size=2
t4 add num=76 size=1
t5 remove num=70 size=0
方法3:使用Lock和Condition实现
代码实现
java
private static ReentrantLock lock = new ReentrantLock();
private static Condition notEmpty = lock.newCondition();
private static Condition notFull = lock.newCondition();
private static int SIZE = 10;
private static LinkedList<Integer> list = new LinkedList<>();
private static volatile boolean flag = true;
@Test
public void testCase01() {
ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
private volatile int index = 0;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "t" + (index++));
}
});
for (int i = 0; i < 5; i++) {
threadPool.submit(new Producer());
threadPool.submit(new Consumer());
}
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
threadPool.shutdown();
}
private static class Producer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
lock.lock();
try {
if (list.size() >= SIZE) {
notEmpty.signalAll();
try {
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is full " +
" size=" + list.size());
} else {
int num = new Random().nextInt(100);
list.addLast(num);
System.out.println(Thread.currentThread().getName() + " add num=" + num +
" size=" + list.size());
notEmpty.signalAll();
}
} finally {
lock.unlock();
}
}
}
}
private static class Consumer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
lock.lock();
if (list.size() <= 0) {
notFull.signalAll();
try {
notEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is full " +
" size=" + list.size());
} else {
int num = list.removeFirst();
System.out.println(Thread.currentThread().getName() + " remove num=" + num +
" size=" + list.size());
notFull.signalAll();
}
}
}
}
执行结果
实现方式和wait和notify一样
ini
t8 add num=70 size=1
t6 add num=4 size=2
t0 add num=17 size=3
t4 add num=22 size=4
t7 remove num=70 size=3
t7 remove num=4 size=2
方法4:使用信号量来实现
实现代码
java
private static int SIZE = 10;
private static Semaphore notEmpty = new Semaphore(0);
private static Semaphore notFull = new Semaphore(SIZE);
private static LinkedList<Integer> list = new LinkedList<>();
private static volatile boolean flag = true;
private static AtomicInteger curSize = new AtomicInteger(0);
@Test
public void testCase01() {
ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
private volatile int index = 0;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "t" + (index++));
}
});
for (int i = 0; i < 5; i++) {
threadPool.submit(new Producer());
threadPool.submit(new Consumer());
}
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
threadPool.shutdown();
}
private static class Producer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
try {
notFull.acquire();
int num = new Random().nextInt(100);
list.addLast(num);
System.out.println(Thread.currentThread().getName() + " add num=" + num +
" size=" + curSize.addAndGet(1));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
notEmpty.release();
}
}
}
}
private static class Consumer implements Runnable {
@Override
public void run() {
while (flag) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
try {
notEmpty.acquire();
int num = list.removeFirst();
System.out.println(Thread.currentThread().getName() + " remove num=" + num +
" size=" + curSize.addAndGet(-1));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
notFull.release();
}
}
}
}
执行结果
执行结果会乱序
ini
t0 add num=60 size=1
t8 add num=79 size=2
t6 add num=58 size=4
t4 add num=56 size=3
t2 add num=49 size=4
t7 remove num=60 size=3
t1 remove num=58 size=0
t5 remove num=56 size=1