java线程池--阻塞队列

版权声明:本文为博主原创文章,如需转载请标明出处。 https://blog.csdn.net/DGH2430284817/article/details/87189214

       在线程池的线程全部开启后,之后的线程任务就会先放入阻塞队列,由阻塞队列把线程任务发放到线程池的空闲线程,当阻塞队列没有任务时,线程池就会一直阻塞,直到新的线程任务进入,具体的线程池细节可参考我的另一篇博客:https://blog.csdn.net/DGH2430284817/article/details/86697761

          下面我们就使用synchronized锁来实现基础的阻塞队列

初始化阻塞队列参数:

public class BlockingQueue {
	    private int maxSize;//阻塞队列的最大容量
	    private List<String> list = new ArrayList<String>(); //元素集合
	    private final Object lock = new Object();//用final修饰锁,防止锁在使用的时候被修改引用导致锁失效
	    

	    public BlockingQueue(int maxSize) {
	        this.maxSize = maxSize;
	        System.out.println("阻塞队列-" + Thread.currentThread().getName() + "已初始化长度为"  + this.maxSize + "的队列");
	    }
  
            .
            . 其他方法代码
            .
            .

}

加入元素方法:

	    /**加入元素,如果阻塞队列满了则阻塞,直到有被元素取出
	     * @param element
	     * @throws InterruptedException
	     */
	    public void put(String element) throws InterruptedException {
	        synchronized (lock) {
	            if (this.list.size() == this.maxSize) {
	                try {
	                    System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已满,阻塞并等待元素取出");
	                    lock.wait();
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
	            }
	            Thread.sleep(1000 * 1);//等待一秒
	            this.list.add(element);
	            System.out.println("阻塞队列:" + Thread.currentThread().getName() + "向队列中加入元素:" + element);
	            lock.notifyAll();
	        }
	    }

获取元素方法take():

	    /**获取元素,如果阻塞队列为空则阻塞,直到有新元素加入
	     * @return
	     */
	    public String take() {
	        synchronized (lock) {
	            if (this.list.size() == 0) {
	                try {
	                    System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已空,阻塞并等待元素加入");
	                    lock.wait();
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
	            }
	            String result = this.list.remove(0);
	            System.out.println("阻塞队列:" + Thread.currentThread().getName() + "从队列中取出元素:" + result);
	            lock.notifyAll();
	            return result;
	        }
	    }

获取元素方法poll():

	    /**获取元素,如果阻塞队列为空则返回空
	     * @return
	     */
	    public String poll() {
	        synchronized (lock) {
	            if (this.list.size() == 0) {
                    System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已空,返回null");
	            	return null;
	            }
	            String result = this.list.remove(0);
	            System.out.println("阻塞队列:" + Thread.currentThread().getName() + "从队列中取出元素:" + result);
	            lock.notifyAll();
	            return result;
	        }
	    }

测试:

	    public static void main(String[] args) {
	    	BlockingQueue queue =  new BlockingQueue(5);

	        new Thread(() -> {
	        	try {
	            queue.put("1");
	            queue.put("2");
	            queue.put("3");
	            queue.put("4");
	            queue.put("5");
	            queue.put("6");
	            queue.put("7");
	            queue.put("8");
	            queue.put("9");
	            queue.put("10");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
	        }, "A").start();

	        new Thread(() -> {
	            queue.take();
	            queue.take();
	            queue.take();
	            queue.take();
	            queue.take();
	        }, "C").start();
	        
	        new Thread(() -> {
	            queue.poll();
	            queue.poll();
	            queue.poll();
	            queue.poll();
	            queue.poll();
	        }, "B").start();
	        
	    }

结果:

阻塞队列-main已初始化长度为5的队列
阻塞队列:A向队列中加入元素:1
阻塞队列:A向队列中加入元素:2
阻塞队列:B从队列中取出元素:1
阻塞队列:B从队列中取出元素:2
阻塞队列:B队列已空,返回null
阻塞队列:B队列已空,返回null
阻塞队列:B队列已空,返回null
阻塞队列:C队列已空,阻塞并等待元素加入
阻塞队列:A向队列中加入元素:3
阻塞队列:A向队列中加入元素:4
阻塞队列:C从队列中取出元素:3
阻塞队列:C从队列中取出元素:4
阻塞队列:C队列已空,阻塞并等待元素加入
阻塞队列:A向队列中加入元素:5
阻塞队列:A向队列中加入元素:6
阻塞队列:A向队列中加入元素:7
阻塞队列:A向队列中加入元素:8
阻塞队列:C从队列中取出元素:5
阻塞队列:C从队列中取出元素:6
阻塞队列:C从队列中取出元素:7
阻塞队列:A向队列中加入元素:9
阻塞队列:A向队列中加入元素:10

注:由结果发现阻塞队列加入的元素没有全部取出来,只取到了7个,还有3个没取,那是因为用poll方法去元素时如果队列没有元素时会直接返回空,有元素才返回值,poll方法取了三次空,所以这三次都没拿到队列元素,在线程池也是如此,临时线程采用poll方法读队列的线程任务,如果没有任务了返回空,回收临时线程。而线程池的线程用take方法,有元素取值,没元素就阻塞,等待新的元素进入再获取。

猜你喜欢

转载自blog.csdn.net/DGH2430284817/article/details/87189214