闲谈java线程池三两事

Executors线程池

三种阻塞队列

  •  ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界
  • LinkedBlockingQueue<>();//基于链表的先进先出队列,无界
  •  SynchronousQueue<>();//无缓冲的等待队列,无界

四种拒绝策略

  • ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
  • ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
  • ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
  • ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务

五种线程池

  • Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
  • Executors.newFixedThreadPool(3);//固定大小的线程池
  • Executors.newScheduledThreadPool(2);
  • Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
  • new ThreadPoolExecutor();//默认线程池,可控制参数比较多 

当线程池中的线程出现异常

execute没有返回值。可以执行任务,但无法判断任务是否成功完成。(实现Runnable接口)

submit返回一个future。可以用这个future来判断任务是否成功完成。(实现Callable接口)

执行方式是execute时,可以看到堆栈异常的输出。当执行方式是submit时,堆栈异常没有输出。但是调用Future.get()方法时,可以捕获到异常。不会影响线程池里面其他线程的正常执行,线程池会把这个线程移除掉,并创建一个新的线程放到线程池中。

超时控制

通过join(long timeout)或者java.util.concurrent.Future.get(long timeout, TimeUnit unit) 启动一个监听线程,当监听线程通过上述方法判断任务线程超时,再调用interrupt或者cancel方法退出线程。

优雅的关闭线程池

  • shutdownNow:线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。将线程池状态修改为STOP,然后调用线程池里的所有线程的interrupt方法。正常情况下,线程池里的线程里面正处于IO阻塞,则会导致报InterruptedException,如果正在正常执行,则不受影响,继续执行完这个任务。
  • shutdown:线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。将线程池的状态修改为SHUTDOWN状态,然后调用interruptIdleWorkers方法,来中断空闲的线程,正在执行线程池里任务的线程不会被中断。

使用shutdownNow方法,可能会引起报错,使用shutdown方法可能会导致线程关闭不了。当我们使用shutdownNow方法关闭线程池时,一定要对任务里进行异常捕获。

当使用shuwdown方法关闭线程池时,一定要确保任务里不会有永久阻塞等待的逻辑,否则线程池就关闭不了。

调用完shutdownNow和shuwdown方法后,并不代表线程池已经完成关闭操作,它只是异步的通知线程池进行关闭处理。如果要同步等待线程池彻底关闭后才继续往下执行,需要调用awaitTermination方法进行同步等待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值