线程池

线程池

线程池参数

  • 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(线程池彻底终止)

posted @ 2020-04-09 22:03  海绵爱上星  阅读(123)  评论(0编辑  收藏  举报