队列与并发 遇到的问题
package com.study0320;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class TestPC {
public final static Integer MAX_COUNT = 1000000;
volatile static ArrayBlockingQueue<Object> q;
volatile static Object notEmpty;
volatile static Object notFull;
volatile static int i = 0;
public static void main(String[] args) throws InterruptedException {
notEmpty = new Object();
notFull = new Object();
q = new ArrayBlockingQueue<Object>(1000000);
Consumer c = new Consumer(q, notEmpty, notFull, i);
c.start();
Consumer c1 = new Consumer(q, notEmpty, notFull, i);
c1.start();
//
// Consumer c2 = new Consumer(q, notEmpty);
// c2.start();
//
//
// Consumer c3 = new Consumer(q, notEmpty);
// c3.start();
Thread.sleep(500);
Producer p = new Producer(q, notEmpty, notFull);
p.start();
Producer p2 = new Producer(q, notEmpty, notFull);
p2.start();
}
}
class Producer extends Thread {
private ArrayBlockingQueue<Object> q;
private final Object notEmpty;
private final Object notFull;
Producer(ArrayBlockingQueue<Object> q, Object notEmpty, Object notFull) {
this.q = q;
this.notEmpty = notEmpty;
this.notFull = notFull;
}
@Override
public void run() {
int i = 0;
while (true) {
synchronized (notEmpty) {
if (q.size() == 0) {
notEmpty.notifyAll();
}
synchronized (notFull) {
if (q.size() == TestPC.MAX_COUNT) {
try {
System.err.println(Thread.currentThread().getName() + " 队列已满, size: " + q.size());
notFull.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
q.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " add: " + i++);
}
}
}
}
class Consumer extends Thread {
private volatile ArrayBlockingQueue<Object> q;
private final Object notEmpty;
private final Object notFull;
private int i;
Consumer(ArrayBlockingQueue<Object> q, Object notEmpty, Object notFull, int i) {
this.q = q;
this.notEmpty = notEmpty;
this.notFull = notFull;
this.i= i;
}
@Override
public void run() {
while (true) {
// System.out.println("即将执行:" + Thread.currentThread().getName() + "size: " + q.size());
synchronized (notEmpty) {
try {
// System.out.println(Thread.currentThread().getName() + " 抢到锁, size:" + q.size()); // 放开a 和 b行就不会有NPE
if (q.size() == 0) {
System.out.println(Thread.currentThread().getName() + " 即将等待");
System.out.println("消耗了: " + i + "个元素");
notEmpty.wait();
System.out.println(Thread.currentThread().getName() + " 已被唤醒");
}
synchronized (notFull) {
if (q.size() == TestPC.MAX_COUNT) {
System.err.println(Thread.currentThread().getName() + " 队列已满 ");
System.out.println("消耗了: " + i + "个元素");
notFull.notifyAll();
}
}
System.out.println(Thread.currentThread().getName() + " 不为空: " + q.size());
Integer o = (Integer) q.take(); // 被唤醒时已为空 会报空指针 这就是为什么会报NPE的原因 对嘛?
// Queue的poll会在队列为空的时候取出数据 而引发空指针灾难
// ArrayBlockingQueue的take会在队列为空的时候 发生阻塞
System.err.println(Thread.currentThread().getName() + " take: " + o.toString());
i++;
} catch (InterruptedException e) {
System.err.println(Thread.currentThread().getName() + " size : " + q.size());
e.printStackTrace();
}
}
}
}
}
class Checker implements Runnable {
private Queue<Object> q;
Checker(Queue<Object> q) {
this.q = q;
}
@Override
public void run() {
try {
Thread.sleep(200);
while (true) {
if (0 == q.size()) {
Thread.currentThread().interrupt();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
有什么问题?
浙公网安备 33010602011771号