• 线程池设计思路


     

    线程池的思路和生产者消费者模型是很接近的。
    1. 准备一个任务容器
    2. 一次性启动10个 消费者线程
    3. 刚开始任务容器是空的,所以线程都wait在上面。
    4. 直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒notify
    5. 这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
    6. 如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行这些任务。

    在整个过程中,都不需要创建新的线程,而是循环使用这些已经存在的线程
    线程池设计思路

    package maptoxml;


    import java.util.LinkedList;

    public class ThreadPool {

    // 线程池大小
    int threadPoolSize;

    // 任务容器
    LinkedList<Runnable> tasks = new LinkedList<Runnable>();

    // 试图消费任务的线程

    public ThreadPool() {
    threadPoolSize = 10;

    // 启动10个任务消费者线程
    synchronized (tasks) {
    for (int i = 0; i < threadPoolSize; i++) {
    new TaskConsumeThread("任务消费者线程 " + i).start();
    }
    }
    }

    public void add(Runnable r) {
    synchronized (tasks) {
    tasks.add(r);
    // 唤醒等待的任务消费者线程
    tasks.notifyAll();
    }
    }

    class TaskConsumeThread extends Thread {
    public TaskConsumeThread(String name) {
    super(name);
    }

    Runnable task;

    public void run() {
    System.out.println("启动: " + this.getName());
    while (true) {
    synchronized (tasks) {
    while (tasks.isEmpty()) {
    try {
    tasks.wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    task = tasks.removeLast();
    // 允许添加任务的线程可以继续添加任务
    tasks.notifyAll();

    }
    System.out.println(this.getName() + " 获取到任务,并执行");
    task.run();
    }
    }
    }

    }

    package maptoxml;

    public class TestThread {

    public static void main(String[] args) {
    ThreadPool pool = new ThreadPool();

    for (int i = 0; i < 5; i++) {
    Runnable task = new Runnable() {
    @Override
    public void run() {
    //System.out.println("执行任务");
    //任务可能是打印一句话
    //可能是访问文件
    //可能是做排序
    }
    };

    pool.add(task);

    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    }

    }

    创造一个情景,每个任务执行的时间都是1秒
    刚开始是间隔1秒钟向线程池中添加任务

    然后间隔时间越来越短,执行任务的线程还没有来得及结束,新的任务又来了。
    就会观察到线程池里的其他线程被唤醒来执行这些任务

    package maptoxml;

    public class TestThread {

    public static void main(String[] args) {
    ThreadPool pool = new ThreadPool();
    int sleep = 1000;
    for (int i = 0; i < 5; i++) {
    Runnable task = new Runnable() {
    @Override
    public void run() {
    //System.out.println("执行任务");
    //任务可能是打印一句话
    //可能是访问文件
    //可能是做排序
    }
    };

    pool.add(task);

    try {
    Thread.sleep(sleep);
    sleep = sleep>100?sleep-100:sleep;
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

    }

    }

  • 相关阅读:
    [转贴]CAD取消选择对象的七种方法
    DELPHI 调用标准C接口DLL char *value
    WPF 本地化资源文件及运行时切换语言
    html input 是否允许浏览器字段默认值 或者之前输入的值
    利用ArcEngine开发地图发布服务,将mxd文档一键发布成wmts,并根据需要对地图进行空间查询,返回客户端geojson
    前端工程化入门必看
    php如何获取mp4视频的封面图片
    报错Use of undefined constant SWOOLE_PROCESS assumed 'SWOOLE_PROCESS' (this will throw an Error in a future version of PHP)
    Linux安装FFmpeg
    正则表达式
  • 原文地址:https://www.cnblogs.com/chinaifae/p/10193774.html
Copyright © 2020-2023  润新知