队列与并发 遇到的问题

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();
        }
    }
    
}










有什么问题?














posted on 2019-03-21 10:20  zach2019  阅读(129)  评论(0)    收藏  举报

导航