java线程池实现生产者消费者模式

本人并发小白,如果有可以优化的地方欢迎评论交流~

题目如下:

​  15个生产者生产1000条数据(从1开始,每生产一条加1),并向消息队列中存放字符串(“第m个生产者生产数据n”),同时3个消费者消费数据,并将数据n累加最后输出

代码如下:

生产者:

package com.lcy.thread.parta;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 功能描述:生产者
 *
 * @author liuchaoyong
 * @version 1.0
 * @date 2020/1/7 19:49
 */
public class Producer implements Runnable{

    LinkedBlockingQueue<String> queue;

    private AtomicInteger data;

    Producer(LinkedBlockingQueue<String> queue,AtomicInteger data){
        this.queue=queue;
        this.data=data;
    }

    @Override
    public void run() {

        //小于1000就一直生产
        while (data.get() <= Test.MAX) {
            String s = "第" + Thread.currentThread().getName() + "个生产者生产" + data.getAndIncrement();
            System.out.println(s);
            queue.offer(s);
        }

    }
}

消费者:

package com.lcy.thread.parta;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 功能描述:消费者
 *
 * @author liuchaoyong
 * @version 1.0
 * @date 2020/1/7 20:00
 */
public class Consumer implements Runnable{

    private LinkedBlockingQueue<String> queue;

    private AtomicInteger sum;

    private AtomicInteger time;

    Consumer(LinkedBlockingQueue<String> queue,AtomicInteger time,AtomicInteger sum){
        this.queue=queue;
        this.time=time;
        this.sum=sum;
    }

    @Override
    public void run() {
        while (time.get() != Test.MAX) {
            String poll = queue.poll();
            if (poll != null) {
                sum.getAndAdd(Integer.parseInt(poll.substring(poll.lastIndexOf("产") + 1)));
                time.getAndIncrement();
            }
        }
    }
}

测试类:

package com.lcy.thread.parta;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 功能描述:
 *
 * @author liuchaoyong
 * @version 1.0
 * @date 2020/1/7 20:07
 */
public class Test {

    public static final int MAX = 1000;

    /**
     *消息队列
     */
    private static LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();

    /**
     * 生产者当前生产的数据
     */
    private static AtomicInteger data = new AtomicInteger(1);

    /**
     * 累加器
     */
    private static AtomicInteger sum = new AtomicInteger(0);

    /**
     * 消费者当前消费次数
     */
    private static AtomicInteger time = new AtomicInteger(0);

    /**
     * 生产者线程池
     */
    private static ThreadPoolExecutor producerExecutor;

    /**
     * 消费者线程池
     */
    private static ThreadPoolExecutor consumerExecutor;

    static {
        producerExecutor = new ThreadPoolExecutor(15, 15, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new ThreadFactory() {
            private AtomicInteger num = new AtomicInteger(0);

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, num.incrementAndGet() + "");
            }
        });
        consumerExecutor = new ThreadPoolExecutor(3, 3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), (ThreadFactory) Thread::new);
    }


    public static void main(String[] args) {

        for (int i = 0; i < 15; i++) {
            producerExecutor.execute(new Producer(queue, data));
        }
        for (int i = 0; i < 3; i++) {
            consumerExecutor.execute(new Consumer(queue,time, sum));
        }
        //加到1000了就关闭生产者,并等待剩余生产者任务结束
        do {
            if (data.get() == MAX && !producerExecutor.isShutdown()) {
                producerExecutor.shutdown();
            }
        } while (!producerExecutor.isTerminated());
        //取了1000次数据就关闭消费者,并等待消费者任务结束
        while (true) {
            if (time.get() == MAX && !consumerExecutor.isShutdown()) {
                consumerExecutor.shutdown();
                break;
            }
        }
        System.out.println(sum.get());
    }

}
发布了61 篇原创文章 · 获赞 13 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章