线程池的种类和应用

一、线程池作用
线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程 排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程 池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

二、为什么要用线程池
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累趴下(每个线程需要大约 1MB 内存,线程开的越多,消耗的内存也就越大,最后死机)

//创建固定大小的线程池
ExecutorService fPool = Executors.newFixedThreadPool(3);
//创建缓存大小的线程池
ExecutorService cPool = Executors.newCachedThreadPool();
//创建单一的线程池
ExecutorService sPool = Executors.newSingleThreadExecutor();
三、常见的几个线程池

1.newSingleThreadExecutor

ExecutorService sPool = Executors.newSingleThreadExecutor();

单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务。

2.newFixedThreadExecutor(n)

ExecutorService fPool = Executors.newFixedThreadPool(3);

固定数量的线程池,没提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行。

3.newCacheThreadExecutor(推荐使用)

ExecutorService cPool = Executors.newCachedThreadPool();

可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。

4.newScheduleThreadExecutor

ExecutorService executorService= Executors.newScheduledThreadPool(10);

大小无限制的线程池,支持定时和周期性的执行线程。

四、线程池的结构

在这里插入图片描述
一、Executors
Java 里面线程池的顶级接口是 Executor,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。ThreadPoolExecutor 是 Executors 类的底层实现。我们先介绍下 Executors。线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。 Executors可以说是一个工厂类,可以用它来创建不同的线程池。

例如:

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }    

可以看到,他的所有方法都是返回一个类的对象。

二.ExecutorService
java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务。因此一
个 ExecutorService 很类似于一个线程池。实际上,存在于 java.util.concurrent 包里的 ExecutorService 实
现就是一个线程池实现。
java.util.concurrent 包提供了 ExecutorService 接口的以下实现类:
1.ThreadPoolExecutor
2. ScheduledThreadPoolExecutor

3.ExecutorService定义的几个方法:

1、execute(Runnable):
execute(Runnable) 方法要求一个 java.lang.Runnable 对象,然后对它进行异步执行。

2、submit(Runnable):
submit(Runnable) 方法也要求一个 Runnable 实现类,但它返回一个 Future 对象。这个 Future 对象可
以用来检查 Runnable 是否已经执行完毕。

3、 submit(Callable):
submit(Callable) 方法类似于 submit(Runnable) 方法,除了它所要求的参数类型之外。Callable 实例除了
它的 call() 方法能够返回一个结果之外和一个 Runnable 很相像。Runnable.run() 不能够返回一个结果。
Callable 的结果可以通过 submit(Callable) 方法返回的 Future 对象进行获取。

4、invokeAny(…):
invokeAny() 方法要求一系列的 Callable 或者其子接口的实例对象。调用这个方法并不会返回一个 Future,
但它返回其中一个 Callable 对象的结果。无法保证返回的是哪个 Callable 的结果 – 只能表明其中一个已
执行结束。如果其中一个任务执行结束(或者抛了一个异常),其他 Callable 将被取消。

5、invokeAll(…):
invokeAll() 方法将调用你在集合中传给 ExecutorService 的所有 Callable 对象。invokeAll() 返回一系列
的 Future 对象,通过它们你可以获取每个 Callable 的执行结果。
记住,一个任务可能会由于一个异常而结束,因此它可能没有 “成功”。无法通过一个 Future 对象来告知我
们是两种结束中的哪一种。

6.shutdown();
使用 shutdown 和 shutdownNow 可以关闭线程池
两者的区别:
shutdown 只是将空闲的线程 interrupt() 了,shutdown()之前提交的任务可以继续执行直到结束。
shutdownNow 是 interrupt 所有线程, 因此大部分线程将立刻被中断。之所以是大部分,而不是全部 ,
是因为 interrupt()方法能力有限。

四、ThreadPoolExecutor
java.util.concurrent.ThreadPoolExecutor 是 ExecutorService 接口的一个实现。ThreadPoolExecutor 使用
其内部池中的线程执行给定任务(Callable 或者 Runnable)。
ThreadPoolExecutor 包含的线程池能够包含不同数量的线程。池中线程的数量由以下变量决定:
1.corePoolSize
2.maximumPoolSize

当一个任务委托给线程池时,如果池中线程数量低于 corePoolSize,一个新的线程将被创建,即使池中可能尚有空 闲 线 程 。 如 果 内 部 任 务 队 列 已 满 , 而 且 有 至 少 corePoolSize 正 在 运 行 , 但 是 运 行 线 程 的 数 量 低 于maximumPoolSize,一个新的线程将被创建去执行该任务。

ExecutorService threadPoolExecutor =
new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
);

构造方法参数列表解释:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。

五、ScheduledPoolExecutor
java.util.concurrent.ScheduledExecutorService 是一个 ExecutorService, 它能够将任务延后执行,或者间隔
固定时间多次执行。 任务由一个工作者线程异步执行,而不是由提交任务给 ScheduledExecutorService 的那个线程执行。

ScheduledExecutorService 的实现:
ScheduledExecutorService 是一个接口,你要用它的话就得使用 java.util.concurrent 包里对它的某个实现类。
ScheduledExecutorService 具有以下实现类:ScheduledThreadPoolExecutor

创建一个 ScheduledExecutorService:
如何创建一个 ScheduledExecutorService 取决于你采用的它的实现类。但是你也可以使用 Executors 工厂类
来创建一个 ScheduledExecutorService 实例。比如:

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

ScheduledExecutorService 的使用:
一旦你创建了一个 ScheduledExecutorService,你可以通过调用它的以下方法:
1.schedule (Callable task, long delay, TimeUnit timeunit)

2.schedule (Runnable task, long delay, TimeUnit timeunit)

3.scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)

4.scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值