1 为什么使用线程池重用线程池的线程,避免因为线程的创建和销毁锁带来的性能开销。
有效控制线程池的最大并发数,避免大量的线程之间因抢占系统资源而阻塞。
能够对线程进行简单的管理,并提供一下特定的操作如:可以提供定时、定期、单线程、并发数控制等功能。
2 线程池可能带来的风险死锁
任何多线程应用程序都有死锁风险。当一组进程或线程中的每一个都在等待一个只有该组中另一个进程才能引起的事件时,我们就说这组进程或线程死锁了。资源不足
一般是由于线程池设置过大引起,需要合理设置线程池大小。并发错误
线程池和其它排队机制依靠使用 wait() 和 notify() 方法,这两个方法都难于使用。如果编码不正确,那么可能丢失通知,导致线程保持空闲状态,尽管队列中有工作要处理。线程泄露
任务抛出一个 RuntimeException 或一个 Error 时。如果池类没有捕捉到它们,那么线程只会退出而线程池的大小将会永久减少一个。当这种情况发生的次数足够多时,线程池最终就为空,而且系统将停止,因为没有可用的线程来处理任务。请求过载
线程池任务队列中,待执行的任务堆积过多,消耗太多的系统资源并引起资源缺乏。
3 java四种常用的线程池实现Executors.newCachedThreadPool():可缓存线程池。
一种线程数量不定的线程池,并且其最大线程数为Integer.MAX_VALUE,这个数是很大的,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。但是线程池中的空闲线程都有超时限制,这个超时时长是60秒,超过60秒闲置线程就会被回收。调用execute将重用以前构造的线程(如果线程可用)。这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会超时被停止。Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池。
当线程 处于空闲状态时,它们并不会被回收,除非线程池被关闭了,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列(没有大小限制)中。由于newFixedThreadPool只有核心线程并且这些核心线程不会被回收,这样它更加快速底相应外界的请求。Executors.newScheduledThreadPool(int n):创建一个定长线程池,支持定时及周期性任务执行。
它的线程数量是固定的,它可安排给定延迟后运行命令或者定期地执行,这类线程池主要用于执行定时任务和具有固定周期的重复任务。Executors.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。