Java学习笔记之线程池
2017-02-21 11:58
288 查看
自JDK5之后,Java推出了一个在并发编程中很实用的软件包,java.util.concurrent。
创建并返回设置有常用配置字符串的 ExecutorService 的方法。
创建并返回设置有常用配置字符串的 ScheduledExecutorService 的方法。
创建并返回“包装的”ExecutorService 方法,它通过使特定于实现的方法不可访问来禁用重新配置。
创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
创建并返回非闭包形式的 Callable 的方法,这样可将其用于需要 Callable 的执行方法中。
2.创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用他们。
3.创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程。
4.创建一个可安排在给定延迟后运行命令或定期地执行的线程池
以下是每种线程池的使用示例:
1.FixedThreadPool
结果:
代码创建了一个固定大小的线程池,容量为3个线程,从结果来看,前3个线程首先执行,空闲下来的时候才会执行第4和第5个任务。在FixedThreadPool中,有一个固定大小的池,如果当前需要执行的任务超过了池大小,那么多于的任务等待状态,直到有空闲下来的线程执行任务,而当执行的任务小于池大小,空闲的线程也不会去销毁。
2. CachedThreadPool
上段代码其它地方不变,将newFixedThreadPool方法换成newCachedThreadPool方法。
5个任务是交替执行的,CachedThreadPool会创建一个缓存区,将初始化的线程缓存起来,如果线程有可用的,就使用之前创建好的线程,如果没有可用的,就新创建线程,终止并且从缓存中移除已有60秒未被使用的线程。
3.SingleThreadExecutor
上段代码其它地方不变,将newFixedThreadPool方法换成newSingleThreadExecutor方法。
5个任务顺序执行,SingleThreadExecutor得到的是一个单个的线程,这个线程会保证你的任务执行完成,如果当前线程意外终止,会创建一个新线程继续执行任务,这和我们直接创建线程不同,也和newFixedThreadPool(1)不同。
4.ScheduledThreadPool
ScheduledThreadPool可以定时的或延时的执行任务。
而且,线程池和主线程是无关的,即使主线程关闭,线程池中的线程仍旧允许。可以通过如下代码来验证,后面循环中的线程组中并没有主线程。
本文参考自:高爽|Coder——Java 线程池
Executor
执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。ExecutorService
实现了Executor,并提供了一些管理方法。是一个使用更广泛的接口。ScheduledExecutorService
一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。Executors
包含此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。(也就是通过此类可以获得实现了这些接口的对象)。此类支持以下方法:创建并返回设置有常用配置字符串的 ExecutorService 的方法。
创建并返回设置有常用配置字符串的 ScheduledExecutorService 的方法。
创建并返回“包装的”ExecutorService 方法,它通过使特定于实现的方法不可访问来禁用重新配置。
创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
创建并返回非闭包形式的 Callable 的方法,这样可将其用于需要 Callable 的执行方法中。
创建功能不同的线程池
1.创建一个可重用固定线程集合的线程池ExecutorService threadPool = Executors.newFixedThreadPool(3);
2.创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用他们。
ExecutorService threadPool = Executors.newCachedThreadPool();
3.创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程。
ExecutorService threadPool = Executors.newSingleThreadExecutor();
4.创建一个可安排在给定延迟后运行命令或定期地执行的线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);//
以下是每种线程池的使用示例:
1.FixedThreadPool
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolTest { public static void main(String[] args){ ExecutorService threadPool = Executors.newFixedThreadPool(3); for(int i = 1; i < 6; i++){ final int taskID = i; threadPool.execute(new Runnable() { @Override public void run() { for(int i = 1; i < 5; i++){ try{ Thread.sleep(20); }catch(InterruptedException e){ } System.out.println("第"+taskID+"次任务——第"+i+"次执行"); } } }); } threadPool.shutdown(); } }
结果:
第2次任务——第1次执行 第3次任务——第1次执行 第1次任务——第1次执行 第1次任务——第2次执行 第3次任务——第2次执行 第2次任务——第2次执行 第3次任务——第3次执行 第1次任务——第3次执行 第2次任务——第3次执行 第1次任务——第4次执行 第3次任务——第4次执行 第2次任务——第4次执行 第5次任务——第1次执行 第4次任务——第1次执行 第4次任务——第2次执行 第5次任务——第2次执行 第5次任务——第3次执行 第4次任务——第3次执行 第5次任务——第4次执行 第4次任务——第4次执行
代码创建了一个固定大小的线程池,容量为3个线程,从结果来看,前3个线程首先执行,空闲下来的时候才会执行第4和第5个任务。在FixedThreadPool中,有一个固定大小的池,如果当前需要执行的任务超过了池大小,那么多于的任务等待状态,直到有空闲下来的线程执行任务,而当执行的任务小于池大小,空闲的线程也不会去销毁。
2. CachedThreadPool
上段代码其它地方不变,将newFixedThreadPool方法换成newCachedThreadPool方法。
第5次任务——第1次执行 第1次任务——第1次执行 第4次任务——第1次执行 第3次任务——第1次执行 第2次任务——第1次执行 第3次任务——第2次执行 第5次任务——第2次执行 第1次任务——第2次执行 第4次任务——第2次执行 第2次任务——第2次执行 第3次任务——第3次执行 第1次任务——第3次执行 第2次任务——第3次执行 第4次任务——第3次执行 第5次任务——第3次执行 第2次任务——第4次执行 第5次任务——第4次执行 第4次任务——第4次执行 第1次任务——第4次执行 第3次任务——第4次执行
5个任务是交替执行的,CachedThreadPool会创建一个缓存区,将初始化的线程缓存起来,如果线程有可用的,就使用之前创建好的线程,如果没有可用的,就新创建线程,终止并且从缓存中移除已有60秒未被使用的线程。
3.SingleThreadExecutor
上段代码其它地方不变,将newFixedThreadPool方法换成newSingleThreadExecutor方法。
第1次任务——第1次执行 第1次任务——第2次执行 第1次任务——第3次执行 第1次任务——第4次执行 第2次任务——第1次执行 第2次任务——第2次执行 第2次任务——第3次执行 第2次任务——第4次执行 第3次任务——第1次执行 第3次任务——第2次执行 第3次任务——第3次执行 第3次任务——第4次执行 第4次任务——第1次执行 第4次任务——第2次执行 第4次任务——第3次执行 第4次任务——第4次执行 第5次任务——第1次执行 第5次任务——第2次执行 第5次任务——第3次执行 第5次任务——第4次执行
5个任务顺序执行,SingleThreadExecutor得到的是一个单个的线程,这个线程会保证你的任务执行完成,如果当前线程意外终止,会创建一个新线程继续执行任务,这和我们直接创建线程不同,也和newFixedThreadPool(1)不同。
4.ScheduledThreadPool
public class ScheduledThreadPoolTest { public static void main(String[] args){ ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(3); schedulePool.schedule(new Runnable() { @Override public void run() { System.out.println("延迟爆炸,砰"); } }, 5,TimeUnit.SECONDS); schedulePool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("延迟循环爆炸,砰砰砰"); } }, 5, 3, TimeUnit.SECONDS); System.out.println("主线程执行到末尾"); } }
ScheduledThreadPool可以定时的或延时的执行任务。
而且,线程池和主线程是无关的,即使主线程关闭,线程池中的线程仍旧允许。可以通过如下代码来验证,后面循环中的线程组中并没有主线程。
public class ScheduledThreadPoolTest { public static void main(String[] args){ ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(3); schedulePool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("*****************"); int num = Thread.activeCount(); Thread[] list = new Thread[num]; Thread.currentThread().getThreadGroup().enumerate(list); for(int i=0;i<list.length;i++){ System.out.println(list[i].getName()); } System.out.println("*****************"); } }, 5, 3, TimeUnit.SECONDS); System.out.println("——————————————————————————————"); int num = Thread.activeCount(); Thread[] list = new Thread[num]; Thread.currentThread().getThreadGroup().enumerate(list); for(int i=0;i<list.length;i++){ System.out.println(list[i].getName()); } System.out.println("——————————————————————————————"); System.out.println("主线程执行到末尾"); } }
本文参考自:高爽|Coder——Java 线程池
相关文章推荐
- java网络编程学习笔记(四):线程池的实现
- java多线程学习笔记之自定义线程池
- Java学习笔记(74)------------线程池
- java学习笔记.04——线程池
- java学习笔记 线程池的使用1
- spring boot学习笔记2-java 线程池
- [学习笔记]Java代码构建一个线程池的自己学习写的实例,用这个你会更好的理解文章内容
- java学习笔记(线程池)
- JAVA学习笔记之多线程专题(二):线程池概述
- Java学习笔记—多线程(线程池框架Executor总结,转载)
- java.util.concurrent 学习笔记(2) 线程池基础
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
- Java线程和线程池学习笔记
- Java学习笔记_线程池
- JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法
- Java并发读书学习笔记(七)——线程池
- java大数据学习笔记(二) 线程池与应用
- Android(java)学习笔记211:Android线程池形态
- Java学习笔记46:Java 线程池
- JAVA jdk 线程池学习笔记