多线程阻塞队列生产者-消费者代码样例实现

模拟运行一下多线程下一个队列的元素的新增、提取(删除)。

使用队列:ArrayBlockingQueue

新增元素方法offer(ele),队列满时时,不抛异常。

提取且删除元素方法poll(),队列为空时,不抛异常。

我们简单以生产消费某个数字来展示。

一、常规的多线程创建方式

代码如下:

import com.sun.javafx.binding.StringFormatter;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

public class TestZone {

    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10, true);

        //创建10个消费者
        for (int i=0; i<10; i++) {
            Thread consuTd = new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            //取出元素,不抛异常
                            int headNum = queue.poll(100, TimeUnit.MILLISECONDS);
                            System.out.println(StringFormatter.format("消费者:%s,消费掉产品%s。", Thread.currentThread().getName() , headNum).getValue());

                            Thread.sleep(1000);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            });
            consuTd.start();

        }

        //创建10个生产者
        for (int i=0; i<10; i++) {
            Thread prdTd = new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            int randomNum = new Random().nextInt()*1000 + 1;

                            //插入元素,队列满,不抛异常
                            boolean insertFlg = queue.offer(randomNum);
                            if(insertFlg){
                                System.out.println(StringFormatter.format("生产者:%s,新增产品%s。", Thread.currentThread().getName() , randomNum).getValue());
                            }else{
                                System.out.println(StringFormatter.format("生产者:%s,新增产品失败!", Thread.currentThread().getName()).getValue());
                            }
                            Thread.sleep(1000);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            });
            prdTd.start();
        }
    }
}

运行结果:

二、线程池的多线程创建方式实现

自定义一个ThreadFactory类

package demo.springboot.web;

import java.util.concurrent.ThreadFactory;

public class MyThreadFactory implements ThreadFactory {

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        System.out.println("线程:"+ t.getName() +"创建!");
        return t;
    }

}

线程池实现两个生产者+两个消费者:

package demo.springboot.web;

import com.sun.javafx.binding.StringFormatter;

import java.util.Random;
import java.util.concurrent.*;

public class ThreadPoolTest {
    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(10, true);
        ArrayBlockingQueue<Runnable> runnableBlockingQueue = new ArrayBlockingQueue<Runnable>(10, true);


        ThreadFactory threadFactory = new MyThreadFactory();
/*
        ThreadPoolExecutor.AbortPolicy ThreadPoolExecutor 默认策略 直接抛出java.util.concurrent.RejectedExecutionException异常
        ThreadPoolExecutor.DiscardPolicy 放弃当前任务,并且不会抛出任何异常
        ThreadPoolExecutor.DiscardOldestPolicy 会将队列中最早添加的元素移除,再尝试添加,如果失败则按该策略不断重试
        ThreadPoolExecutor.CallerRunsPolicy 由调用线程(提交任务的线程)处理该任务,如果调用线程是主线程,那么主线程会调用执行器中的execute方法来执行改任务
*/
        ExecutorService executorServicePrd = new ThreadPoolExecutor(5,10, 1000,
                TimeUnit.MILLISECONDS, runnableBlockingQueue, threadFactory, new ThreadPoolExecutor.AbortPolicy());
        //生产者1
        executorServicePrd.execute(new Runnable() {
            @Override
            public void run() {

                while(true){
                    try {
                        int randomNum = new Random().nextInt(1000);

                        //插入元素,队列满时,不抛异常
                        boolean insertFlg = blockingQueue.offer(randomNum);
                        if(insertFlg){
                            System.out.println(StringFormatter.format("生产者:%s,新增产品%s。", Thread.currentThread().getName() , randomNum).getValue());
                        }else{
                            System.out.println(StringFormatter.format("生产者:%s,阻塞队列满了,生产失败!", Thread.currentThread().getName()).getValue());
                        }
                        Thread.sleep(100);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });

        //生产者2
        executorServicePrd.execute(new Runnable() {
            @Override
            public void run() {

                while(true){
                    try {
                        int randomNum = new Random().nextInt(1000);

                        //插入元素,队列满时,不抛异常
                        boolean insertFlg = blockingQueue.offer(randomNum);
                        if(insertFlg){
                            System.out.println(StringFormatter.format("生产者:%s,新增产品%s。", Thread.currentThread().getName() , randomNum).getValue());
                        }else{
                            System.out.println(StringFormatter.format("生产者:%s,阻塞队列满了,生产失败!", Thread.currentThread().getName()).getValue());
                        }
                        Thread.sleep(100);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });

        ExecutorService executorServiceConsummer = new ThreadPoolExecutor(5,10, 1000,
                TimeUnit.MILLISECONDS, runnableBlockingQueue, threadFactory, new ThreadPoolExecutor.AbortPolicy());

        //消费者1
        executorServiceConsummer.execute(new Runnable() {
            @Override
            public void run() {

                while(true){
                    try {
                        //取出元素,队列为空时,不抛异常
                        Integer headNum = blockingQueue.poll(100, TimeUnit.MILLISECONDS);
                        if(null!=headNum && headNum>0) {
                            System.out.println(StringFormatter.format("消费者:%s,消费掉产品%s。", Thread.currentThread().getName(), headNum).getValue());
                        }else{
                            System.out.println(StringFormatter.format("消费者:%s,阻塞队列为空,消费失败!",Thread.currentThread().getName()).getValue());
                        }
                        Thread.sleep(100);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });

        //消费者2
        executorServiceConsummer.execute(new Runnable() {
            @Override
            public void run() {

                while(true){
                    try {
                        //取出元素,队列为空时,不抛异常
                        Integer headNum = blockingQueue.poll(100, TimeUnit.MILLISECONDS);
                        if(null!=headNum && headNum>0) {
                            System.out.println(StringFormatter.format("消费者:%s,消费掉产品%s。", Thread.currentThread().getName(), headNum).getValue());
                        }else{
                            System.out.println(StringFormatter.format("消费者:%s,阻塞队列为空,消费失败!",Thread.currentThread().getName()).getValue());
                        }
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

备注:如果想查看生产者生产超额而生产失败,消费者消费完了而消费失败的两种极端情况,

修改生产者或者消费者线程的休眠时间即可。

运行结果:

 

三、

更复杂、更贴近现实的多线程阻塞队列实现,待续……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值