type
status
date
slug
summary
tags
category
icon
password
example-row
example-row

new Thread VS 线程池

new Thread的缺点:
  • 每次new Thread新建对象性能差。
  • 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
  • 缺乏更多功能,如定时执行、定期执行、线程中断。
线程池的优点:
  • 重用存在的线程,减少对象创建、消亡的开销,性能佳。
  • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  • 提供定时执行、定期执行、单线程、并发数控制等功能。

java线程池

Java通过Executors提供四种线程池:newCachedThreadPoolnewFixedThreadPoolnewScheduledThreadPoolnewSingleThreadExecutor

newCachedThreadPool

可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程(缓存中已有 60 秒钟未被使用的线程),若无可回收,则新建线程。
源码:
可以使用ThreadPoolExecutor构造函数创建具有相似属性但不同细节(例如,超时参数)的ThreadPoolExecutor
  • newCachedThreadPool是没有核心线程数的
  • newCachedThreadPool的最大线程数是Integer.MAX_VALUE
  • 如果存在60s内的线程还没被使用,则会被终止并且从缓存中移除
  • 线程存活的时间单位是秒,其余的基本是毫秒
  • 采用了SynchronousQueue队列
使用示例:
运行上面的程序,main方法在经过大概60s的时间,程序会自动终止,原因是因为newCachedThreadPool线程池已经将task执行完毕,那些存活的线程在超过60s的空闲的时候,就会被终止调,且从缓存中移除。

newFixedThreadPool

创建一个指定长度的线程池,可控制线程最大并发数,超出的线程会在队列中等待。
源码:
使用示例:
运行上面的程序,main方法会每过1秒,打印5条数据。当调用 ExecutorService.shutdown() 方法后,线程池会停止接受新任务,但是还有一些任务正在执行或者在等待执行。awaitTermination() 方法是一个阻塞方法,可以判断线程池中的任务是否全部执行完毕,用于在子线程执行完后,执行主线程方法,在子线程执行完之前,awaitTermination()方法会一直阻塞。打印如下:
如果把awaitTermination()方法放到ExecutorService.shutdown()前执行则会在子线程执行完后,因为awaitTermination()阻塞导致主线程不会退出。
 

newScheduledThreadPool

用于延迟及周期性的任务。
源码:
使用示例:
运行上面的程序,main方法第一次执行是3秒后,这里执行耗时1秒,以2秒为周期,下一次执行为5秒后,依次类推。
  • 执行耗时>等待时间:当前任务执行完成后,马上执行下一个任务周期
  • 执行耗时>等待时间:下一周期的执行时间=等待时间 - 执行耗时
如果把scheduleAtFixedRate方法改成scheduleWithFixedDelay方法,两个方法请求参数是一样的,但是scheduleWithFixedDelay方法不管执行时间多长,下一周期的执行时间都是在当前周期执行完成后,等待固定的等待时间进入执行阶段。
schedule()方法使用示例:
submit方法使用示例:
submit()方法可以在指定任务执行完成前,阻塞线程等待结果返回。

newSingleThreadExecutor

单线程池,顾名思义,这个线程池有且仅有一条线程用于执行任务。
源码:
使用示例:

Executor vs ExecutorService vs Executors

  • ExecutorService 接口继承自Executor接口。
  • Executor接口定义了 execute()方法用来接收一个Runnable接口的对象,而 ExecutorService 接口中的 submit()方法可以接受RunnableCallable接口的对象。
  • Executor中的 execute() 方法不返回任何结果,而 ExecutorService 中的 submit()方法可以通过一个 Future 对象返回结果。
  • ExecutorService还提供用来控制线程池的方法。比如:调用shutDown()方法终止线程池。
  • Executors类提供工厂方法用来创建不同类型的线程池。

参考

 
【java笔记008】基本类型【java笔记010】多线程之UncaughtExceptionHandler
  • Twikoo