zoukankan      html  css  js  c++  java
  • Java多线程-线程池ThreadPoolExecutor

    为什么要使用线程池?

    如果每个请求都创建一个线程去处理,那么服务器的CPU资源很快就会被耗尽,导致宕机。使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

    线程池的作用

    1)方便控制线程的数量,避免了因无休止的创建线程导致系统崩溃

    2)减少了线程创建和消耗的时间

    ThreadPoolExecutor创建线程池

    示例:

    /**
     * 线程池持有者单例
     */
    public class MyThreadPoolHolder {
        private static ThreadPoolExecutor executor;
    
        private MyThreadPoolHolder() {
        }
    
        public static ThreadPoolExecutor getInstance() {
            if (executor == null) {
                synchronized (MyThreadPoolHolder.class) {
                    if (executor == null) {
                        // Java虚拟机可用的CPU数量
                        int availableProcessor = Runtime.getRuntime().availableProcessors();
                        // 核心线程数
                        int corePoolSize = availableProcessor * 2 + 1;
                        // 最大线程数
                        int maxPoolSize = corePoolSize * 2;
                        // 线程存活时间
                        long keepAliveSeconds = 60L;
                        // 线程队列容量
                        int queueCapacity = 1000;
                        // 线程名称前缀
                        String threadNamePrefix = "MyThread - ";
                        // 设置拒绝策略,默认是 ThreadPoolExecutor.AbortPolicy(),丢弃任务并抛出异常
                        RejectedExecutionHandler rejectPolicy = new ThreadPoolExecutor.AbortPolicy();
    
                        // 使用 ThreadPoolExecutor 创建线程池
                        executor =  new ThreadPoolExecutor(corePoolSize,
                                maxPoolSize,
                                keepAliveSeconds,
                                TimeUnit.SECONDS,
                                new LinkedBlockingDeque<Runnable>(queueCapacity),
                                new MyThreadFactory(threadNamePrefix),
                                rejectPolicy);
                    }
                }
            }
    
            return executor;
        }
    }
    
    /**
     * 线程工程类
     */
    class MyThreadFactory implements ThreadFactory {
        /**
         * 线程名称前缀
         */
        private String threadNamePrefix;
        /**
         * 线程索引
         */
        private int threadIndex = -1;
        /**
         * 是否守护线程
         */
        private boolean isDaemon;
    
        public MyThreadFactory(String threadNamePrefix) {
            this.threadNamePrefix = threadNamePrefix;
            this.isDaemon = false;
        }
    
        public MyThreadFactory(String threadNamePrefix, boolean isDaemon) {
            this.threadNamePrefix = threadNamePrefix;
            this.isDaemon = isDaemon;
        }
    
        @Override
        public Thread newThread(Runnable target) {
            String threadName;
            synchronized (this) {
                threadIndex++;
                threadName = threadNamePrefix + threadIndex;
            }
            Thread thread = new Thread(target, threadName);
            thread.setDaemon(isDaemon);
            return thread;
        }
    }

    使用线程池提交不需要返回值的任务

    public class Test {
        public static void main(String[] args) {
            Runnable r1 = new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 10; i++) {
                        System.out.println("r1执行,输出: " + i);
                    }
                }
            };
    
            Runnable r2 = new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 10; i++) {
                        System.out.println("r2执行,输出: " + i);
                    }
                }
            };
            // 提交任务
            MyThreadPoolHolder.getInstance().execute(r1);
            MyThreadPoolHolder.getInstance().execute(r2);
        }
    }

    运行结果:

    使用线程池提交需要返回值的任务

    public class Test {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Callable<List<String>> task1 = new Callable<List<String>>() {
                @Override
                public List<String> call() throws Exception {
                    List<String> list = new ArrayList<>();
                    for (int i = 1; i <= 10; i++) {
                        System.out.println("-----task1,运行----");
                        list.add("task1,值:" + i);
                    }
                    return list;
                }
            };
            Callable<List<String>> task2 = new Callable<List<String>>() {
                @Override
                public List<String> call() throws Exception {
                    List<String> list = new ArrayList<>();
                    for (int i = 1; i <= 10; i++) {
                        System.out.println("-----task2,运行----");
                        list.add("task2,值:" + i);
                    }
                    return list;
                }
            };
            // 提交任务
            Future<List<String>> future1 = MyThreadPoolHolder.getInstance().submit(task1);
            Future<List<String>> future2 = MyThreadPoolHolder.getInstance().submit(task2);
    
            Thread.sleep(3000);
            System.out.println("任务提交之后,就开始运行了,并不是在Future.get()的时候才运行的");
            // 合并结果
            List<String> listRes = new ArrayList<>();
            listRes.addAll(future1.get());
            listRes.addAll(future2.get());
    
            for (String item : listRes) {
                System.out.println(item);
            }
        }
    }

    运行结果:

     

  • 相关阅读:
    [BZOJ4755][JSOI2016]扭动的回文串(manacher+Hash)
    十二省联考2019部分题解
    [BZOJ2959]长跑(LCT+并查集)
    [BZOJ4541][HNOI2016]矿区(平面图转对偶图)
    笛卡尔树
    [CF896C]Willem, Chtholly and Seniorious(珂朵莉树)
    [BZOJ4349]最小树形图
    [BZOJ1858][SCOI2010]序列操作(线段树)
    [PA2014]Parking
    [PA2014]Budowa
  • 原文地址:https://www.cnblogs.com/lkc9/p/12575684.html
Copyright © 2011-2022 走看看