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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章