前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用阻塞队列和线程池简单实现生产者和消费者场景

用阻塞队列和线程池简单实现生产者和消费者场景

作者头像
MindMrWang
发布2018-04-24 17:35:17
1.9K0
发布2018-04-24 17:35:17
举报
文章被收录于专栏:Java学习之路Java学习之路

本例子仅仅是博主学习阻塞队列和后的一些小实践,并不是真正的应用场景!

生产者消费者场景是我们应用中最常见的场景,我们可以通过ReentrantLock的Condition和对线程进行wait,notify同通信来实现生产者和消费者场景,前者可以实现多生产者和多消费者模式,后者仅可以实现一生产者,一消费者模式。

今天我们就利用阻塞队列来实现下生产者和消费者模式(里面还利用了线程池)。 看过我关于阻塞队列博文的朋友已经知道,阻塞队列其实就是由ReentrantLock实现的!

场景就不描述了,为简单的多生产者和多消费者! 上代码:

生产线程:

代码语言:javascript
复制
public class ProductThread extends Thread {
    private int taskNum;
    private ArrayBlockingQueue queue;
    public ProductThread(int taskNum,ArrayBlockingQueue queue) {
        this.taskNum = taskNum;
        this.queue = queue;
    }
    public void run() {
        try {
            //模拟生产
            Thread.currentThread().sleep(5000);
            System.out.println("开始生产");
            queue.add(taskNum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

消费线程:

代码语言:javascript
复制
public class ConsumerThread extends Thread {
    private ArrayBlockingQueue queue;
    public ConsumerThread(ArrayBlockingQueue queue) {
        this.queue = queue;
    }
    
    public void run() {
        System.out.println("准备消费");
            int taskNum;
            try {
                taskNum = (int) queue.take();
                System.out.println("消费了"+taskNum);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
    }
}

主线程(主方法):

代码语言:javascript
复制
public class ProductAndConsumer {
    
    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(20);
        //为多生产者和多消费者分别开创的线程池
        ThreadPoolExecutor productPool = 
                new ThreadPoolExecutor(10,20,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(5),new ThreadPoolExecutor.CallerRunsPolicy());
        ThreadPoolExecutor consumerPool = 
                new ThreadPoolExecutor(10,20,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(5),new ThreadPoolExecutor.CallerRunsPolicy());
        
        System.out.println("start");
        for(int i = 0;i<100;i++) {
            
            productPool.execute(new ProductThread(i,queue));
            consumerPool.execute(new ConsumerThread(queue));
        }
        productPool.shutdown();
        consumerPool.shutdown();
    }
}

上面的代码,我为生产者和消费者分别开了线程池,因为在实际的应用中可能出现生产者和消费者不对等的情况,所以我们应该根据实际情况来设定线程池的参数,以适应不同场景! 在创建线程池的时候要加一个饱和处理的方式,我们上一节写线程池的饱和处理的时候有提及到,如果不加参数,会默认选择抛出异常,我上面选择的饱和策略是将饱和的任务交给调用线程(即主线程)处理,这个也应该根据实际情况来定,我们同样可以实现RejectedExecutionHandler接口,自己来定义这个饱和异常!

以上仅是博主学习自己写的例子,可能在一些情况下考虑的不周到,还请指教! 2018.4.18 21:31

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档