Thread pool



1. Thread Pool

Thread pools and database connection pool of the same meaning, put on a set of multiple threads, the threads are allocated from the collection when there are tasks, when the task is not complete destruction of the thread, into the thread pool waiting for the next task, reducing the the number of threads created and destroyed, improve system efficiency, as part of creation and destruction 重操作. If each has a task to create a thread, a large influx of job creation will lead to too many threads and memory overflow




2. Excutor

java.util.concurrent.Executor provide a series of thread pool associated with the interface, and implementation class, in which the extracted portion to explain conventional


UML 图:


ExecutorService interface methods:


AbstractExecutorService class method:

  • Executor interface defined in the execute (Runnable command) method
  • ExecutorService definition of the relevant life-cycle method thread
  • AbstractExecutorService provides a default implementation
  • ThreadPoolExecutor recommend the use of the thread pool class
  • ForkJoinPool later found a thread pool class, from 1.7 some, not discussed





3. ThreadPoolExecutor

This class provides a common way to create a thread pool, according to different parameters passed to create a different thread pools, take a look at the constructor

public ThreadPoolExecutor(
    
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler) {
    
    //省略具体逻辑,单看参数
}


  • corePoolSize: a core number of threads
    • If the existing number of threads than the number of kernel threads, create new threads to process the request
    • If the number of existing threads than the number of kernel threads, but less than the maximum number of threads, the only full team to create a new thread
    • If the core number of threads equal to the maximum number of threads, create a fixed size thread pool
    • If the maximum number of threads is infinite, then any thread pool size
  • maximumPoolSize: The maximum number of threads
  • keepAliveTime: Idle Hold Time
    • If the number of threads than the existing core number of threads, and beyond remain idle time, the excess threads will be destroyed
  • unit: the unit idle time
  • workQueue: queuing strategy
    • Synchronous transfer: not placed in the queue, but the waiting thread to execute it. If the current thread is not performed, it is likely to open a new thread.
    • No limit strategy: if the core threads are working, the thread will be placed in the queue. Therefore, no more than the number of threads core threads
    • 有界限策略:可以避免资源耗尽,但是一定程度上减低了吞吐量
  • threadFactory:创建线程的工厂
  • handler:拒绝策略
    • 直接抛出异常
    • 使用调用者的线程来处理(多出的相当于没使用线程池)
    • 直接丢掉这个任务
    • 丢掉最老的任务




4. 线程池的状态

  • RUNNING:线程池能接受新任务,以及对新添加的任务进行处理
  • SHUTDOWN:线程池不接受新任务,但会对已添加的任务进行处理
  • STOP:线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务
  • TIDYING:所有的任务已终止,ctl记录的"任务数量"为0,线程池会变为TIDYING状态,当线程池变为TIDYING状态时,会执行钩子函数terminated(),terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理,可以通过重载terminated()函数来实现
  • TERMINATED:线程池真正的终止




5. 线程池方法

execute(),submit(),shutdown(),shutdownNow() 是添加任务和关闭线程池的方法,前两者进行相应逻辑判断再考虑是否创建新线程,后两者是关闭线程池,区别于后者不等其任务完成就中断线程




6. 快捷创建线程池

在Executor类中,有下面几个静态方法来快捷创建线程池,下面写三个:

  • newFixedThreadPool:corePoolSize和maximumPoolSize相等
  • newCachedThreadPool:若新任务进来,没空闲进程会立马创建
  • SingleThreadExecutor:单线程,从队列中取任务执行




7. 线程任务


  • 获取线程的结果:
    • Future:Futrue模式就是Action先给Invoker一个未来(future),其实也就是票据,Invoker就可以继续接下来的步骤而无需等待Action结果的返回,通过 future.get() 可以获得返回值




  • 提交任务的种类:
    • Runnable:重写里面的run方法
    • Callable(可以认为是Runnable的扩展,多了返回值或异常):重写call方法
public static void main(String[] args) {
    
    //快捷线程池
    ExecutorService pool = Executors.newFixedThreadPool(10);
    
    //没有返回值
    Runnable runnable = () -> System.out.println("Runnable任务");
    
    //有返回值
    Callable callable = () -> {
        String msg = "Callable任务";
        System.out.println(msg);
        return msg;
    };
    
    //提交任务,并获取返回值
    Future f1 = pool.submit(runnable);
    Future f2 = pool.submit(callable);
    
    try {
        System.out.println("f1:" + f1.get());
        System.out.println("f2:" + f2.get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    
    //关闭线程池
    pool.shutdown();
}
Callable任务
Runnable任务
f1:null
f2:Callable任务




  • 提交任务的方式:
    • submit:可以接收Runnable,和Callable,有返回值和异常,底层还是用excute
    • execute ,只能接收Runnable,没有返回值

submit底层是用execute实现的:

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);     //把Callable变成RunnableFuture
    execute(ftask);         //把RunnableFuture传入execute
    return ftask;
}

Callable会被包装成RunnableFuture,在RunnableFuture的run中会调用callable的call方法,然后把返回值或异常放入该类的静态变量中




8.线程池实现

public static void main(String[] args) {
    
    //核心线程
    int corePoolSize = 5;
    //最大线程
    int maximumPoolSize = 10;
    //保持空闲时间
    long keepAliveTime = 10;
    //空闲时间单位,秒
    TimeUnit unit = TimeUnit.SECONDS;
    //排队策略,基于数组结构的有界阻塞队列
    BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(5);
    //设置创建线程的工厂,可以预设部分内容:eg:守护进程,优先级
    ThreadFactory threadFactory = Executors.defaultThreadFactory();
    //拒绝策略
    RejectedExecutionHandler handler = new AbortPolicy();;
    
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,
                                                                   maximumPoolSize,
                                                                   keepAliveTime,
                                                                   unit,
                                                                   workQueue,
                                                                   threadFactory,
                                                                   handler);
    
    Callable callable = () -> {
        String msg = "Callable任务";
        System.out.println(msg);
        return msg;
    };
    
    threadPoolExecutor.submit(() -> System.out.println("线程测试1"));
    threadPoolExecutor.submit(callable);

}
<!-- 打印 -->
线程测试1
Callable任务




Guess you like

Origin www.cnblogs.com/Howlet/p/12233870.html