zoukankan      html  css  js  c++  java
  • 线程池

    线程池

    线程池参数

    • corePoolSize:核心线程数大小
    • maximumPoolSize:线程池最大线程数
    • keepAliveTime:线程池中非核心线程空闲的存活时间(与是否超过核心线程数有关)
    • unit:线程存活时间单位
    • workQueue:存放任务的阻塞队列
    • handler:饱和策略
    • threadFactory:设置创建线程的工厂,一般默认
    核心线程和最大线程数的区别?

    任务提交至后,判断核心线程数是否已满?未满的话,创建一个线程。否则进入阻塞队列workQueue。此时无关最大线程数。

    提交的任务后,阻塞队列已满,看是否超过最大线程数,没有的话,创建线程执行。

    若超过最大线程数,则执行饱和策略handler。

    执行完后,存活时间有keepAliveTime。

    拒绝策略handler

    4种:

    1. Abort——直接抛出异常RejectExecutionException,阻止系统正常工作
    2. CallerRuns——直接在调用者线程中运行
    3. DiscardOldest:丢弃即将执行的任务
    4. Discard:直接丢弃

    默认:AbortPolicy

    阻塞队列

    • ArrayBlockingQueue——有界
    • PriorityBlockingQueue —— 无界
    • LinkedListBlockingQueue——可看做无界,默认大小为Integer.MAX_VALUE
    • DelayBlockingQueue——基于PriorityBlockingQueue

    线程池类型

    1. 固定大小的线程池
    2. 计划任务线程池
    3. 单线程线程池
    4. 可缓存线程池

    1、固定大小的线程池

    package com.concurrency;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadPoolDemo {
        public static class MyTask implements Runnable{
    
            @Override
            public void run() {
                System.out.println(System.currentTimeMillis() +
                        "Thread ID" + Thread.currentThread().getId()
                );
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            MyTask myTask = new MyTask();
            ExecutorService service = Executors.newFixedThreadPool(5);
            for(int i = 0;i < 10;i++){
                service.submit(myTask);
            }
        }
    }

    调用new FixedThreadPool(),会创建一个具有固定数目线程的线程池。每次提交一个任务,就创建一个线程,知道达到线程池的最大大小(和设置的一样)。

    若其中某个线程执行异常结束,则线程池会补充一个新线程。

    使用哪种队列?

    无界的LinedBlockingQueue。

    使用无界队列的线程池会导致内存占用飙升吗?

    会。假如线程任务执行时间过长,则会导致队列的任务越积越多,最终导致OOM Error。

    适合场景?

    适合确定cpu被长时间占用的情况。

    工作机制?
    1. 提交任务时,线程池创建一个线程执行任务。
    2. 到达核心线程数目时,新的任务添加至LinkedBlokingQueue
    3. 线程任务执行完后,去阻塞队列去任务。

    2、计划任务线程池

    此线程池会在指定时间对线程进行调度。

    //schedule() 在指定时间执行任务
    //ss.schedule(myTask, 10, TimeUnit.SECONDS);

    //scheduleAtFixedRate() 周期性执行任务
    ss.scheduleAtFixedRate(myTask, 2, 2, TimeUnit.SECONDS);
    适合场景

    周期性的执行任务的场景。

    3、单线程线程池

    1. 核心线程数:1
    2. 最大线程数:1
    3. 阻塞队列:LinkedBlockingQueue

    适合场景:串行执行任务的场景,一个任务一个任务的执行。

    4、可缓存线程池

    1. 核心线程数为:0
    2. 最大线程数:Integer.MAX_VALUE
    3. 阻塞队列为:SynchronousQueue

    工作机制:

    1. 没有核心线程,任务直接添加到SynchronousQueue队列。
    2. 若有空闲线程,则取出任务执行
    3. 没有空闲线程,则新建一个线程执行
    4. 执行完任务,线程再存活60s

    适合场景:并发执行大量、短期的小任务

     线程池的状态

    5种:

    Running (接受新任务,处理阻塞队列中的任务)——SHUTDOWN(不会接受任务,但是会处理阻塞队列任务) —— STOP(不会接收、不会处理阻塞队列) —— TIDYING(所有任务已完成)——TERMINATED(线程池彻底终止)

    一回生,二回熟
  • 相关阅读:
    hadoop之 mr输出到hbase
    北美IT公司大致分档
    推荐系统(协同过滤,slope one)
    机器学习的常见面试问题
    关联规则之Aprior算法(购物篮分析)
    Python的Set和List的性能比较 + 两者之间的转换
    Python 集合set添加删除、交集、并集、集合操作符号
    3.算法-二叉树遍历
    1.系统设计-概要
    2算法-二分查找
  • 原文地址:https://www.cnblogs.com/zzytxl/p/12669932.html
Copyright © 2011-2022 走看看