package com.liquidnet.commons.lang.util;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: TreadUtil
 * @Package com.liquidnet.commons.lang.util
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2022/3/17 18:52
 */
@Slf4j
public class FixedSizeThreadPool {
    //手写线程池需要准备什么？
    // 1.需要1个仓库
    private BlockingQueue<Runnable> blockingQueue;
    // 2.需要一个线程的集合
    private List<Thread> workers;


    //3. 需要具体干活的线程
    public static class Worker extends Thread {
//        图上的卡车
        // 1.到我们的仓库中去拿东西（blockingQueue）
        //

        private FixedSizeThreadPool pool;

        // 创建构造方法，声明自己属于哪个线程池
        public Worker(FixedSizeThreadPool pool) {
            this.pool = pool;
        }

        @Override
        public void run() {
//            开始工作
            while (this.pool.isWorking || this.pool.blockingQueue.size() > 0) {
                Runnable task = null;
//                从队列中拿东西的时候，需要的是阻塞
                try {
                    if (this.pool.isWorking) {
                        task = this.pool.blockingQueue.take();
                    } else {
                        task = this.pool.blockingQueue.poll();
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (task != null) {
                    task.run();
                    log.info("线程：{}执行完毕", Thread.currentThread().getName());
//                    System.out.println("线程："+Thread.currentThread().getName());
                }


            }
        }
    }

    // 线程池的初始化,构造函数
    public FixedSizeThreadPool(int poolSize, int taskSize) {
        if (poolSize <= 0 || taskSize <= 0)
            throw new IllegalArgumentException("非法参数");
        this.blockingQueue = new LinkedBlockingQueue<>(taskSize);
        this.workers = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < poolSize; i++) {
            Worker work = new Worker(this);
            work.start();
            workers.add(work);

        }
    }

    //    把任务提交到仓库中的办法
    public boolean submit(Runnable task) {
        if (isWorking) {
            return this.blockingQueue.offer(task);
        } else {
            return false;
        }

    }

    //    关闭的方法：
    //a.仓库停止接收任务
    //b.一旦仓库中还有任务就要继续执行
    //c. 拿任务就不该阻塞
    //d.一旦任务阻塞，我就中断他
    private volatile boolean isWorking = true;

    public void shutDown() {
//    执行关闭即可
        this.isWorking = false;
        for (Thread thread : workers) {
            if (thread.getState().equals(Thread.State.BLOCKED)) {
                thread.interrupt();// 中断线程
            }
        }
    }

    public static void main(String[] args) {
        FixedSizeThreadPool fixedSizeThreadPool = new FixedSizeThreadPool(3, 6);
        for (int i = 0; i < 6; i++) {
            fixedSizeThreadPool.submit(
                    new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("放入线程");
                            try {
                                Thread.sleep(2000L);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                                log.error("一个线程被中断");
                            }
                        }
                    }
            );
        }
        fixedSizeThreadPool.shutDown();
    }

}

