线程池的毒丸方法实现线程池的配比热切换

Posted kokomal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池的毒丸方法实现线程池的配比热切换相关的知识,希望对你有一定的参考价值。

需求:
线程池(采用ThreadPoolExecutor)有2类共计10个作战区线程在跑,都是从blockingQueue里面取武器进行消费,其中5个是对德,另外5个对日,另外有n个生产者线程负责对blockingQueue发送武器;
现在由于中途德国率先投降,需要削减对德的驻军,请问这个多线程代码框架如何设计?
要求:
尽可能采用juc原始的多线程工具;
不允许使用redis和db相关;
blockingQueue里面的消息要全部被消费后才能退出;

/**
 * @Title: ArsenalTester.java
 * @Package: inter
 * @Description: TODO(用一句话描述该文件做什么)
 * @author: 陈元俊
 * @date: 2019年5月24日 下午12:42:23
 * @version V1.0
 * @Copyright: 2019 All rights reserved.
 */
package inter;

import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName: ArsenalTester
 * @Description: 模拟二战武器生产
 * @author: 陈元俊
 * @date: 2019年5月24日 下午12:42:23
 */
public class ArsenalTester {
    private static final String CANCEL_NAZI = "CANCEL_NAZI";
    private static final String CANCEL_JAPAN = "CANCEL_JAPAN";

    /* 兵工厂,这里是生产者 */
    public static class Arsenal implements Runnable {
        private BlockingQueue<String> equipments;
        public static volatile boolean stop = false; // 全局的兵工厂生产开关

        public Arsenal(BlockingQueue<String> equipments) {
            this.equipments = equipments;
        }
        public static AtomicInteger counts = new AtomicInteger();

        @Override
        public void run() {
            while (!stop) {
                String equip = UUID.randomUUID().toString();
                // System.out.println("Arsenal produced " + equip);
                equipments.add(equip);
                counts.incrementAndGet();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
            }
            System.out.println("stop producing!");
        }
    }
    /* 负责对日的司令部 默认5个战区,从兵工厂要装备*/
    public static class FightJapanHQ implements Runnable {
        private BlockingQueue<String> equipments;
        public static AtomicInteger jpcounts = new AtomicInteger();

        public FightJapanHQ(BlockingQueue<String> equipments) {
            this.equipments = equipments;
        }

        @Override
        public void run() {
            while (true) {
                String equip;
                try {
                    equip = equipments.take();
                    if (equip.equals(CANCEL_JAPAN)) {
                        System.out.println("-------------------------FightJapanHQ demolished!"); // 毒丸收到,撤销战区
                        return;
                    } else if (CANCEL_NAZI.equals(equip)) {
                        // System.out.println("DONT GIVE ME NAZI!");
                        equipments.add(equip);
                        continue;
                    }
                    jpcounts.incrementAndGet();
                    System.out.println("Asia HQ fetch " + equip);
                } catch (InterruptedException e) {
                    System.out.println("-=-=-=cannot get");
                }
            }
        }
    }
    /* 负责对德的司令部,默认5个战区,从兵工厂要装备 */
    public static class FightNaziHQ implements Runnable {
        private BlockingQueue<String> equipments;
        public static AtomicInteger nzcounts = new AtomicInteger();

        public FightNaziHQ(BlockingQueue<String> equipments) {
            this.equipments = equipments;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    String equip = equipments.take();
                    if (CANCEL_NAZI.equals(equip)) {
                        System.out.println("-------------------------FightNaziHQ demolished!"); // 毒丸收到,撤销战区
                        return;
                    } else if (CANCEL_JAPAN.equals(equip)) {
                        // System.out.println("DONT GIVE ME JP!");
                        equipments.add(equip);
                        continue;
                    }
                    nzcounts.incrementAndGet();
                    System.out.println("Euro HQ fetch " + equip);
                } catch (InterruptedException e) {
                    System.out.println("-=-=-=cannot get");
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ExecutorService battleField = Executors.newCachedThreadPool();
        BlockingQueue<String> equipments = new ArrayBlockingQueue<>(1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    battleField.submit(new Arsenal(equipments));
                }
                for (int i = 0; i < 5; i++) {
                    battleField.submit(new FightNaziHQ(equipments));
                    battleField.submit(new FightJapanHQ(equipments));
                }
                System.out.println("i am out!"); // 发射后不管
            }

        }).start();
        Thread.sleep(5000);
        System.out.println("=============================Nazi surrendered!============================="); // 德国先投降
        for (int i = 0; i < 4; i++) {
            boolean val = equipments.add(CANCEL_NAZI); // 这里取消掉4个对德战区,保留1个
        }
        Thread.sleep(5000);
        Arsenal.stop = true;
        System.out.println("Celebrate peace"); // 二战胜利!马放南山,但此刻Queue里面大概率仍然有订单!
        for (int i = 0; i < 1; i++) {
            boolean val = equipments.add(CANCEL_NAZI); // 别忘了战后取消剩下的1个对德战区
            // System.out.println("put res " + val);
        }
        for (int i = 0; i < 5; i++) {
            boolean val = equipments.add(CANCEL_JAPAN); // 取消剩下的5个对日战区
            // System.out.println("put res " + val);
        }
        battleField.shutdown();
        while (!battleField.isTerminated()) {
        }
        System.out.println("Totally produced " + Arsenal.counts);
        System.out.println("Finally FightNaziHQ received " + FightNaziHQ.nzcounts.intValue() + " and FightJapanHQ received "
                + FightJapanHQ.jpcounts.intValue());
        System.out.println("equipments now remains " + equipments.size());
    }
}

以上是关于线程池的毒丸方法实现线程池的配比热切换的主要内容,如果未能解决你的问题,请参考以下文章

多线程 线程池的实现原理分析

多线程 线程池的实现原理分析

停止线程池的正确方法

如何实现线程池的 QueueUserWorkItem 方法的延续?

阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第5节 线程池_2_线程池的代码实现

线程池的实现原理