线程(九)-- 线程池

一、基本介绍

线程池:
已经包含了一些线程, 以便直接使用.
优点:避免了频繁创建 / 销毁线程的开销

线程池本身就是生产者 - 消费者模型。
生产者 - 消费者模型介绍

核心操作:
execute: 把一个任务加到线程池中
shutdown: 销毁线程池中的所有线程

线程池的组成:(需要管理两个部分: 将要执行的任务, 正在执行任务的线程)
1. 一个类, 描述具体线程要做的工程(借助 Runnable 表示)
2. 需要一个数据结构来组织若干个任务(BlockingQueue)
3. 先有一个类, 表示工作线程
4. 还需要一个数据结构, 组织若干个线程(List)

二、线程池的实现

	static class Worker extends Thread {
        // 描述当前工作线程
        // 每个 Worker 线程都需要从任务队列中取任务
        // 需要能够获取到任务队列的实例
        private int id = 0;
        private BlockingQueue<Runnable> queue = null;

        public Worker(BlockingQueue<Runnable> queue, int id) {
            this.queue = queue;
            this.id = id;
        }

        @Override
        public void run() {
            // try 包含 while:
            // 目的是只要线程收到异常, 就会立刻结束 run 方法
            // 为 shutdown 方法做准备
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    // 数据结构建成
                    Runnable commend = queue.take();
                    // 如果队列为空, take 就会阻塞
                    // 阻塞到 execute 插入元素
                    System.out.println("Thread " + id + " running");
                    commend.run();
                }
            }catch (InterruptedException e) {
                // 线程被结束
                System.out.println("线程被终止");
            }
        }
    }

    static class ThredPool {
        // 本质就是生产者 消费者模型
        // 调用 execute 的是生产者, 生产了任务
        // worker 线程是消费者, 消费了队列中的任务

        // 阻塞队列用于组织若干个任务
        private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
        // List 用于组织若干个工作线程
        private List<Worker> workers = new ArrayList<>();
        // 线程池内部线程个数(根据实际情况确定)
        private static final int maxWorkerCount = 10;

        // 实现 execute 方法和 shutdown 方法
        public void execute(Runnable command) throws InterruptedException {
            // 加人线程池(加入队列)
            // 也是使用延时加载的方式来创建线程(需要判断池中线程数目是否小于阈值)
            // 若没达到, 则不需新建线程, 否则需要新建一个线程
            if (workers.size() < maxWorkerCount) {
                Worker worker = new Worker(queue, workers.size());
                worker.start();
                workers.add(worker); // 加入 ArrayList 中
            }
            queue.put(command); // 加入阻塞队列中
        }

        public void shutDown() throws InterruptedException {
            // 终止所有线程
            for (Worker worker : workers) {
                worker.interrupt();
                // interrupt(): 中断这个线程
                // 这里的作用只是触发线程的 catch 异常, 让 run 方法结束.
                // 线程结束, 则对应的 join 方法也返回了.
                // 从收到异常到线程结束, 中间还需要执行 catch 中代码, 因此不是瞬时完成.

                // interrupted(): 测试当前线程是否中断。
            }

            // 还需要等待每个线程执行结束
            for (Worker worker : workers) {
                worker.join();
                // join(): 等待这个线程死亡。
            }
        }
    }

    static class Command implements Runnable {
        private int num;

        public Command(int num) {
            this.num = num;
        }

        @Override
        public void run() {
            System.out.println("正在执行任务: " + num);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ThredPool pool = new ThredPool();
        for (int i = 0; i < 1000; i++) {
            // i 不是 final 类修饰, 所以不能再匿名内部类或 lamba 中直接调用, 需要重新写一个类(Command) 传入 i.
            pool.execute(new Command(i));
        }
        Thread.sleep(2000); // 休眠 2 秒
        pool.shutDown();
        System.out.println("线程池已被销毁");
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值