• 架构师养成记--11.Executor概述


    常用方法

    Executors.newFiexdPool(int nThreads);固定线程数量的线程池;

    Executors.newSingleThreadExecutor();单个线程的线程池;

    Executors.newCachedThreadPool();根据实际情况调整线程个数的线程池;每个线程空闲时间60s,过时自动回收;

    Executors.newScheduleThreadPool();固定数量线程池,每个线程都可显现定时器。

    以上几个线程池都是由ThreadPoolExecutor构造出来的

    ThreadPoolExecutor构造方法概述:

    ThreadPoolExecutor(

      int corePoolSize,//核心线程数,线程池刚初始化的时候实例化线程个数

      int maximumPoolSize,//最大线程数

      long keepLongTime,//空闲时间,过时回收

      TimeUnit unit,//时间单位

      BlockingQueue<Runable> worker,//线程暂缓处

      ThreadFactory threadFactory,

      RejectExecuteHandle handle//拒绝执行的方法

    )

    Executors.newScheduledThreadPool

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
    scheduler.scheduleWithFixedDelay(command, 1, 3, TimeUnit.SECONDS);

    command是Thread对象,1后执行,每3秒执行一次。

    自定义线程池的使用

    ThreadPoolExecutor pool = new ThreadPoolExecutor(...);

    传的参数中,队列是什么类型很重要

    有界队列:当前线程数小于corePoolSize,线程立即执行;大于coreSize,并小于maximumPoolSize,线程放入队列;如果队列满了,就执行拒绝方法。

    无界队列:除非资源被耗尽,否则不会发生线程被拒绝的情况。以corePoolSize为准,当前线程数大于corePoolSize,线程就会被加入队列。

    注:pool.shutdown();不会立即把线程池关闭,而是等线程池中的线程都执行完了,线程池才会关闭。

    拒绝策略

    AbortPolicy:系统跑出异常,系统继续执行;

    discardOldest:丢弃最老的任务,再执行当前新任务;

    discardPolicy:丢弃无法执行的任务,不给于任何处理;

    callerRunsPolicy:只要线程没有关,会将当前的线程先执行;

    自定义策略实现RejectedExecutionHandler接口。

    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class UseThreadPoolExecutor2 implements Runnable{
    
        private static AtomicInteger count = new AtomicInteger(0);
        
        @Override
        public void run() {
            try {
                int temp = count.incrementAndGet();
                System.out.println("任务" + temp);
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        public static void main(String[] args) throws Exception{
            //System.out.println(Runtime.getRuntime().availableProcessors());
            BlockingQueue<Runnable> queue = 
                    //new LinkedBlockingQueue<Runnable>();
                    new ArrayBlockingQueue<Runnable>(10);
            ExecutorService executor  = new ThreadPoolExecutor(
                        5,         //core
                        10,     //max
                        120L,     //2fenzhong
                        TimeUnit.SECONDS,
                        queue);
            
            for(int i = 0 ; i < 20; i++){
                executor.execute(new UseThreadPoolExecutor2());
            }
            Thread.sleep(1000);
            System.out.println("queue size:" + queue.size());        //输出结果是10,说明在1秒的时候还有10个线程入队等待
            Thread.sleep(2000);
        }
    
    
    }

    重点看一下自定义策略

    public class UseThreadPoolExecutor1 {
    
    
        public static void main(String[] args) {
            /**
             * 在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
             * 若大于corePoolSize,则会将任务加入队列,
             * 若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
             * 若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。
             * 
             */    
            ThreadPoolExecutor pool = new ThreadPoolExecutor(
                    1,                 //coreSize
                    2,                 //MaxSize
                    60,             //60
                    TimeUnit.SECONDS, 
                    new ArrayBlockingQueue<Runnable>(3)            //指定一种队列 (有界队列)
                    //new LinkedBlockingQueue<Runnable>()
                    , new MyRejected()
                    //, new DiscardOldestPolicy()
                    );
            
            MyTask mt1 = new MyTask(1, "任务1");
            MyTask mt2 = new MyTask(2, "任务2");
            MyTask mt3 = new MyTask(3, "任务3");
            MyTask mt4 = new MyTask(4, "任务4");
            MyTask mt5 = new MyTask(5, "任务5");
            MyTask mt6 = new MyTask(6, "任务6");
            
            pool.execute(mt1);
            pool.execute(mt2);
            pool.execute(mt3);
            pool.execute(mt4);
            pool.execute(mt5);
            pool.execute(mt6);
            
            pool.shutdown();
            
        }
    }
    import java.net.HttpURLConnection;
    import java.util.concurrent.RejectedExecutionHandler;
    import java.util.concurrent.ThreadPoolExecutor;
    
    public class MyRejected implements RejectedExecutionHandler{
    
        
        public MyRejected(){
        }
        
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.out.println("自定义处理..");
            System.out.println("当前被拒绝任务为:" + r.toString());
            
    
        }
    
    }
    public class MyTask implements Runnable {
    
        private int taskId;
        private String taskName;
        
        public MyTask(int taskId, String taskName){
            this.taskId = taskId;
            this.taskName = taskName;
        }
        
        public int getTaskId() {
            return taskId;
        }
    
        public void setTaskId(int taskId) {
            this.taskId = taskId;
        }
    
        public String getTaskName() {
            return taskName;
        }
    
        public void setTaskName(String taskName) {
            this.taskName = taskName;
        }
    
        @Override
        public void run() {
            try {
                System.out.println("run taskId =" + this.taskId);
                Thread.sleep(5*1000);
                //System.out.println("end taskId =" + this.taskId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
        }
        
        public String toString(){
            return Integer.toString(this.taskId);
        }
    
    }
  • 相关阅读:
    k8s配置 storageclass 本地 NFS debian环境
    [转载] jenkins 设置 查看 环境变量
    debian 安装 nfs server和 客户端
    创建Vue程序
    准备开发环境
    一道易错的SQL面试题
    创建项目、类、对象并添加一个属性(行为、存储状态)
    SQL大神之(1)数据库的死锁模拟
    Python 魔术方法指南
    SQL的concat()replace()和mid()函数的使用
  • 原文地址:https://www.cnblogs.com/sigm/p/6236464.html
Copyright © 2020-2023  润新知