• 线程池


    线程池  


        1、创建一个空的任务容器

      2、在容器中初始化10个执行任务的线程,俗称消费者线程

      3、最开始这个容器是空的,所以线程都wait在上面

      4、直到一个外部线程往这个容器扔了一个“任务”,这时候就会唤醒消费者线程notify

      5、这个消费者线程从容器中取出”任务“,并且执行这个任务,任务完成,wait等待下一次任务到来

      6、如果短时间有很多任务在容器,就会唤醒所有线程notify,去执行这些任务

      在整个过程中,只需要在初始化池子的时候,会加载线程。之后都不会创建线程,而是循环使用已经存在的线程

    自定义一个线程池


       ThreadPool

    package com.thread.thread16;
    
    import java.util.LinkedList;
    
    public class ThreadPool {
        //线程池大小
        int threadPoolSize;
    
        //任务容器  这个是链表容器  Runnable是线程接口  创建线程需要实现这个接口
        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() {   //重写runnable接口中的run方法
                System.out.println("启动:" + this.getName());        //打印哪个线程被初始化
                while(true) {
                    synchronized (tasks) {       //锁定任务容器
                        while(tasks.isEmpty()) {     //查看任务容器是否有任务  空就返回true 执行wait
                            try {
                                tasks.wait();   //没有任务  让线程们等一下下
                            }catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        //这个时候有任务  tasks不为空
                        task = tasks.removeLast();  //删除最后一个元素 并且返回元素  这个时候是派遣任务给线程
                        //允许添加任务的线程可以继续添加任务
                        tasks.notifyAll();
                    }
                    System.out.println(this.getName() + "获取到任务,并执行");   //看谁抢到这个任务
                    task.run();   //线程争抢该任务
                }
            }
        }
    }

      案例一:测试线程池抢占一个任务

    package com.thread.thread16;
    
    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) {
                    e.printStackTrace();
                }
            }
        }
    }

      效果

       案例二:隔一定时间添加任务到容器中,保证每个线程都被利用到

    package com.thread.thread16;
    
    public class TestThread2 {
        public static void main(String[] args) {
            ThreadPool pool = new ThreadPool();   //创建线程池子
                int sleep = 1000;   //睡眠时间
                while(true) {
                    pool.add(new Runnable() {  //池子里面去扔任务
                        @Override
                        public void run() {
                            System.out.println("执行任务");
                            try{
                                Thread.sleep(1000);  //每个任务 执行久一点   1秒钟   这样 就能看到其他线程也能一起抢占任务
                            }catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                try {
                    Thread.sleep(sleep);
                    sleep = sleep > 100 ?sleep-100:sleep;  //如果执行时间大于100秒  则每次减100   直到减到100以下  直接返回sleep
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

      效果

      案例三:java自带的线程池

    package com.thread.thread16;
    
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread3 {
        public static void main(String[] args)throws InterruptedException {
            //使用自带线程池子
            //10 代表线程池子中初始化了10个
            //15 代表如果10个线程不够了的话  就扩容到15
            //如果60秒  扩容的5个处于空闲  则回收线程  池子保持10个
            //linkedBlockingQueue 任务队列  放任务的地方
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new
                    LinkedBlockingQueue<Runnable>());
            //线程执行
            threadPool.execute(new Runnable() {  //runnable是接口  这里实例化的是runnable接口的实现类
                @Override
                public void run() {    //重写run方法
                    System.out.println("任务1");
                }
            });
        }
    }

      效果

  • 相关阅读:
    Java 最常见的 208 道面试题(第九模块和第十模块答案)
    更灵活的边缘云原生运维:OpenYurt 单元化部署新增 Patch 特性
    高德 Serverless 平台建设及实践
    官宣:恭喜 ChaosBlade 项目进入 CNCF Sandbox
    工商银行分布式服务 C10K 场景解决方案
    云原生的进一步具象化
    阿里云入选 2021 Gartner APM 魔力象限,国内唯一入选云厂商
    云原生下的灰度体系建设
    seata-golang 一周年回顾
    WebAssembly + Dapr = 下一代云原生运行时?
  • 原文地址:https://www.cnblogs.com/HelloM/p/14412091.html
Copyright © 2020-2023  润新知