一、流程:

创建一个任务时,先判断线程池中已有的线程数是否已经超过核心线程数,如果没有,则创建任务;

        如果超过核心线程数,去阻塞队列中,看阻塞队列是否已满,如果没满,则放入阻塞队列中;

        如果阻塞队列已满,则判断当前线程数是否超过最大线程数,如果没超过,则创建一个新的线程;

        如果超过最大线程数,则走异常处理流程(直接抛异常;不处理,丢弃;将阻塞队列中最早的任务丢弃,然后将其放入阻塞队列)

二、异常处理方法:

(一)线程池提交时submit:

1、try catch

2、用Future作为submit的结果,用future.get()方法,接收抛出的异常(future.get()方法要加try catch)

(二)线程中处理异常:

处理未捕获到的异常

Thread t = new Thread(r);
            t.setUncaughtExceptionHandler(
                    (t1, e) -> {
                        System.out.println(t1.getName() + "线程抛出的异常"+e);
                    });
            return t;
           });

(三)重写ThreadExecutorPool的afterExecute方法 处理传递的异常引用

java使用线程池如果请求量过大怎么解决 java线程池满了如何处理_阻塞队列

三、线程池:

newFixedTreadPool固定线程数线程池

  • 核心线程数和最大线程数大小一样
  • 没有所谓的非空闲时间,即keepAliveTime为0
  • 阻塞队列为无界队列LinkedBlockingQueue

java使用线程池如果请求量过大怎么解决 java线程池满了如何处理_java_02

newCachedTreadPool(可缓存线程的线程池)

  • 核心线程数为0
  • 最大线程数为Integer.MAX_VALUE
  • 阻塞队列是SynchronousQueue
  • 非核心线程空闲存活时间为60秒

java使用线程池如果请求量过大怎么解决 java线程池满了如何处理_java_03

  • 提交任务
  • 因为没有核心线程,所以任务直接加到SynchronousQueue队列。
  • 判断是否有空闲线程,如果有,就去取出任务执行。
  • 如果没有空闲线程,就新建一个线程执行。
  • 执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续活下去;否则,被销毁

newSingleTreadExecutor单线程线程池

  • 核心线程数为1
  • 最大线程数也为1
  • 阻塞队列是LinkedBlockingQueue
  • keepAliveTime为0

java使用线程池如果请求量过大怎么解决 java线程池满了如何处理_线程池_04

newScheduledThreadPool(定时及周期执行的线程池)

  • 最大线程数为Integer.MAX_VALUE
  • 阻塞队列是DelayedWorkQueue
  • keepAliveTime为0
  • scheduleAtFixedRate() :按某种速率周期执行
  • scheduleWithFixedDelay():在某个延迟后执行

工作机制

  • 添加一个任务
  • 线程池中的线程从 DelayQueue 中取任务
  • 线程从 DelayQueue 中获取 time 大于等于当前时间的task
  • 执行完后修改这个 task 的 time 为下次被执行的时间
  • 这个 task 放回DelayQueue队列中