系统启动一个新的线程需要与操作系统进行交互,往往消耗的成本比较高,在某些情况下,使用线程池可以很好的提升性能,尤其当成中需要创建大量生存期很短的的线程时,更应该考虑使用线程池 线程池在系统启动时就创建大量的空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个空闲的线程来执行他们的run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run()或call()方法 Java5之前必须手动实现自己的线程池,从Java5开始Java内建支持线程池,Java5新增了一个Executors工厂类来产生线程池,该工厂类包含如下几个静态工厂方法来创建线程池 用完一个线程池后,应该调用该线程池shutdown()方法,该方法将启动线程池的关闭序列,调用该方法后线程池不再接受新任务,但会将以前所有已提交的任务执行完成,当线程池中的所有任务都执行完成后,池中的所有线程都会死亡 为了充分利用多CPU和多核CPU的优势,可以把一个任务拆分成多个“小任务”,把多个小任务放到多个处理器核心上并行执行,多个小任务执行完成后,再将这些执行结果合并起来即可,Java7提供了ForkJoinPool来支持这个操作 Java8扩展了ForkJoinPool,增加了两个静态方法提供通用池功能 创建了ForkJoinPool实例后,就可以调用ForkJoinPool的
此外,线程池还可以有效的控制并发线程的数量,它的最大线程数参数可以控制系统中并发线程数不超过此数
ExecutorService
代表尽快执行线程的线程池,意思就是只要线程池中有空闲线程,就立即执行线程任务,程序只要将一个Runnable对象或Callable对象(线程任务)提交给该线程池,该线程池就会尽快执行改任务,ExecutorService
提供了3个方法:
ScheduledExecutorService
代表可在指定延迟后或周期性地执行线程任务的线程池,它提供了4个方法:
关闭线程池
也可以调用线程池的shutdownNow()方法来关闭线程池,该方法会试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表使用线程池步骤
import java.util.concurrent.*; public class ThreadPoolTest { public static void main(String[] args) throws Exception { // 创建足够的线程来支持4个CPU并行的线程池 // 创建一个具有固定线程数(6)的线程池 ExecutorService pool = Executors.newFixedThreadPool(6); // 使用Lambda表达式创建Runnable对象 Runnable target = () -> { for (var i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "的i值为:" + i); } }; // 向线程池中提交两个线程 pool.submit(target); pool.submit(target); // 关闭线程池 pool.shutdown(); } }
ForkJoinPool
ForkJoinPool是ExecutorService的实现类,因此它是一个特殊的线程池,其常用构造器如下:
System.exit(0);
来终止虚拟机,通用池以及通用池中正在执行的任务都会被终止使用ForkJoinPool
submit(ForkJoinTask task)
或者invoke(ForkJoinTask task)
方法来执行指定任务。
ForkJoinTask代表一个可以并行、合并的任务,ForkJoinTask是一个抽象类它还有两个抽象子类RecursiveAction和RecursiveTask,其中RecursiveAction代表没有返回值的任务,RecursiveTask代表有返回值的任务
import java.util.concurrent.*; // 继承RecursiveAction来实现"可分解"的任务 class PrintTask extends RecursiveAction { // 每个“小任务”只最多只打印50个数 private static final int THRESHOLD = 50; private int start; private int end; // 打印从start到end的任务 public PrintTask(int start, int end) { this.start = start; this.end = end; } @Override protected void compute() { // 当end与start之间的差小于THRESHOLD时,开始打印 if (end - start < THRESHOLD) { for (var i = start; i < end; i++) { System.out.println(Thread.currentThread().getName() + "的i值:" + i); } } else { // 如果当end与start之间的差大于THRESHOLD时,即要打印的数超过50个 // 将大任务分解成两个小任务。 int middle = (start + end) / 2; var left = new PrintTask(start, middle); var right = new PrintTask(middle, end); // 并行执行两个“小任务” left.fork(); right.fork(); } } } public class ForkJoinPoolTest { public static void main(String[] args) throws Exception { var pool = new ForkJoinPool(); // 提交可分解的PrintTask任务 pool.submit(new PrintTask(0, 300)); pool.awaitTermination(2, TimeUnit.SECONDS); // 关闭线程池 pool.shutdown(); } }
import java.util.concurrent.*; import java.util.*; // 继承RecursiveTask来实现"可分解"的任务 class CalTask extends RecursiveTask<Integer> { // 每个“小任务”只最多只累加20个数 private static final int THRESHOLD = 20; private int arr[]; private int start; private int end; // 累加从start到end的数组元素 public CalTask(int[] arr, int start, int end) { this.arr = arr; this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; // 当end与start之间的差小于THRESHOLD时,开始进行实际累加 if (end - start < THRESHOLD) { for (var i = start; i < end; i++) { sum += arr[i]; } return sum; } else { // 如果当end与start之间的差大于THRESHOLD时,即要累加的数超过20个时 // 将大任务分解成两个小任务。 int middle = (start + end) / 2; var left = new CalTask(arr, start, middle); var right = new CalTask(arr, middle, end); // 并行执行两个“小任务” left.fork(); right.fork(); // 把两个“小任务”累加的结果合并起来 return left.join() + right.join(); // ① } } } public class Sum { public static void main(String[] args) throws Exception { var arr = new int[100]; var rand = new Random(); var total = 0; // 初始化100个数字元素 for (int i = 0, len = arr.length; i < len; i++) { int tmp = rand.nextInt(20); // 对数组元素赋值,并将数组元素的值添加到sum总和中。 total += (arr[i] = tmp); } System.out.println(total); // 创建一个通用池 ForkJoinPool pool = ForkJoinPool.commonPool(); // 提交可分解的CalTask任务 Future<Integer> future = pool.submit(new CalTask(arr, 0, arr.length)); System.out.println(future.get()); // 关闭线程池 pool.shutdown(); } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算