Java教程

Java——线程池(二)

本文主要是介绍Java——线程池(二),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、存在风险的线程池创建方式–慎用
创建线程池的方式多种多样,但下面三种不用用在正式环境中,它们分别是:

  • FixedThreadPool:固定大小的线程池
  • SingleThreadExecutor:单个线程的线程池
  • CachedThreadPool:可缓存的线程池

这三种创建方式都在Executors工具类中
在这里插入图片描述
在这里插入图片描述
这些创建线程池的方式都是基于原生创建线程池的方式衍生出来的,我们掌握了原生创建方式,这些创建方式自然也就明白了。

2、Executors线程池工具类

  • FixedThreadPool:固定大小的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
       return new ThreadPoolExecutor(nThreads, nThreads,
                                     0L, TimeUnit.MILLISECONDS,
                                     new LinkedBlockingQueue<Runnable>());
   }

核心线程数和最大线程数相同,意味着该线程池中的线程都是核心线程,空闲线程就不会被销毁。任务队列为链式阻塞队列,此队列有资源耗尽的风险,因为LinkedBlockingQueue的容量为Integer的最大值231,意味着任务队列中的任务数量可高达21(2147483657)之多,容易内存爆表。

  • SingleThreadExecutor:单个线程的线程池
public static ExecutorService newSingleThreadExecutor() {
       return new FinalizableDelegatedExecutorService
           (new ThreadPoolExecutor(1, 1,
                                   0L, TimeUnit.MILLISECONDS,
                                   new LinkedBlockingQueue<Runnable>()));
   }

核心线程数和最大线程数相同,都为1,意味着等待唯一的单线程来执行任务,并保证所有任务按照指定顺序(FIFO或优先级)执行。和FixedThreadPool是一样的问题,此队列有资源耗尽的风险。创建单个线程的线程池有两个方法,一个不带线程工厂,一个带线程工厂。
在这里插入图片描述

输出结果:
"C:\Program Files\Java\jdk1.8.0\bin\java.exe" 
pool-1-thread-1, index=0
pool-1-thread-1, index=1
pool-1-thread-1, index=2

从运行结果可以看出,所有任务都是在单一线程运行的。

  • CachedThreadPool:可缓存的线程池
public static ExecutorService newCachedThreadPool() {
      return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                    60L, TimeUnit.SECONDS,
                                    new SynchronousQueue<Runnable>());
  }

可缓存的线程池意味着线程池里面全都是非核心线程最大线程数是Integer的最大值,空闲线程60秒内没工作就会被销毁风险不言而喻,规避资源耗尽的风险。创建可缓存线程的线程池也有两个方法,一个不带线程工厂,一个带线程工厂。

3、提交任务的2种方式

  • execute

该方法位于Executor接口中,作用是向线程池中提交Runnable任务,Runnable的任务是无返回值的任务。因此该方法 只适合提交无返回值的任务,执行完没有结果返回。如果任务是有返回值的,就需要创建Callable任务,它是一个有返回值的任务,Callable任务执行完,会将执行结果封装到Future对象中,然后返回给调用者,调用者再通过Future对象获取结果。

当该方法提交的任务被拒绝,则抛出任务拒绝异常,提交的任务不能为Null,否则会抛出空指针异常。

  • submit

    submit方法位于Executor Service接口中,它可以提交Callable任务,也可以提交Runnable任务,方法返回一个Future对象,可以看到该对象无返回值,但是为什么还要返回Future对象呢?这是因为Future除了获取任务的执行结果之外,还可以观察任务是否执行完毕以及取消任务。

两种方法区别如下:
在这里插入图片描述

这篇关于Java——线程池(二)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!