你真的了解ForkJoinPool吗?这些技巧让你的代码性能提升十倍!
ForkJoinPool是Java 7中新增的一种线程池实现,它主要用于执行大量的计算密集型任务。ForkJoinPool采用“工作窃取”算法,即当某个线程的任务执行完毕后,会从其他线程的任务队列中窃取任务执行,从而实现负载均衡。
(资料图片仅供参考)
1、线程池简介
线程池是一种常见的多线程编程方式,它可以有效地管理线程的创建、销毁和复用,从而提高程序的性能和稳定性。Java中提供了多种线程池实现,包括ForkJoinPool、Executors、CompletionService等。
2、ForkJoinPool
ForkJoinPool是Java 7中新增的一种线程池实现,它主要用于执行大量的计算密集型任务。ForkJoinPool采用“工作窃取”算法,即当某个线程的任务执行完毕后,会从其他线程的任务队列中窃取任务执行,从而实现负载均衡。
以下是一个使用ForkJoinPool的示例代码:
import java.util.concurrent.*;public class ForkJoinPoolExample { public static void main(String[] args) { int n = 1000000; int[] array = new int[n]; for (int i = 0; i < n; i++) { array[i] = i; } ForkJoinPool pool = new ForkJoinPool(); int sum = pool.invoke(new SumTask(array, 0, n)); System.out.println("Sum: " + sum); }}class SumTask extends RecursiveTask { private int[] array; private int start; private int end; public SumTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected Integer compute() { if (end - start <= 1000) { int sum = 0; for (int i = start; i < end; i++) { sum += array[i]; } return sum; } else { int mid = (start + end) / 2; SumTask left = new SumTask(array, start, mid); SumTask right = new SumTask(array, mid, end); left.fork(); right.fork(); return left.join() + right.join(); } }}
以上代码创建了一个ForkJoinPool,用于计算一个长度为1000000的数组的元素之和。其中,SumTask是一个继承自RecursiveTask的任务类,用于将数组分成若干个子任务进行计算。当子任务的数量小于等于1000时,直接计算子任务的结果;否则,将子任务分成两个部分,分别交给左右两个子任务进行计算,最后将两个子任务的结果相加。
3、Executors
Executors是Java中提供的一个线程池工具类,它可以方便地创建各种类型的线程池。Executors提供了多个静态方法,用于创建不同类型的线程池,例如newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor等。
(1)newFixedThreadPool
newFixedThreadPool是一个固定大小的线程池,它会一直保持固定数量的线程,如果有新的任务提交,但线程池中的线程都在忙碌,那么新的任务就会进入等待队列中等待执行。
以下是一个使用newFixedThreadPool创建线程池的示例代码:
import java.util.concurrent.*;public class FixedThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i < 20; i++) { Runnable task = new Runnable() { @Override public void run() { System.out.println("Task executed by " + Thread.currentThread().getName()); } }; executor.execute(task); } executor.shutdown(); }}
以上代码创建了一个固定大小为5的线程池,提交了20个任务,并关闭了线程池。每个任务的执行会输出执行线程的名称。
(2)newCachedThreadPool
newCachedThreadPool是一个可缓存的线程池,它会根据需要创建新的线程,如果有线程空闲时间超过60秒,就会被回收。如果有新的任务提交,但线程池中的线程都在忙碌,那么就会创建新的线程来处理任务。
以下是一个使用newCachedThreadPool创建线程池的示例代码:
import java.util.concurrent.*;public class CachedThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 20; i++) { Runnable task = new Runnable() { @Override public void run() { System.out.println("Task executed by " + Thread.currentThread().getName()); } }; executor.execute(task); } executor.shutdown(); }}
以上代码创建了一个可缓存的线程池,提交了20个任务,并关闭了线程池。每个任务的执行会输出执行线程的名称。
(3)newSingleThreadExecutor
newSingleThreadExecutor是一个单线程的线程池,它会保证所有任务按照顺序执行,即每个任务都会在前一个任务执行完毕后才会执行。
以下是一个使用newSingleThreadExecutor创建线程池的示例代码:
import java.util.concurrent.*;public class SingleThreadExecutorExample { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 20; i++) { Runnable task = new Runnable() { @Override public void run() { System.out.println("Task executed by " + Thread.currentThread().getName()); } }; executor.execute(task); } executor.shutdown(); }}
以上代码创建了一个单线程的线程池,提交了20个任务,并关闭了线程池。每个任务的执行会输出执行线程的名称。
4、CompletionService
CompletionService是Java中提供的一个用于异步执行任务的工具类,它可以方便地获取已完成的任务的结果。CompletionService内部维护了一个阻塞队列,用于存储已完成的任务的结果。
以下是一个使用CompletionService的示例代码:
import java.util.concurrent.*;public class CompletionServiceExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(5); CompletionService completionService = new ExecutorCompletionService<>(executor); for (int i = 0; i < 10; i++) { final int index = i; Callable task = new Callable() { @Override public Integer call() throws Exception { Thread.sleep((long) (Math.random() * 1000)); return index; } }; completionService.submit(task); } for (int i = 0; i < 10; i++) { Future future = completionService.take(); System.out.println("Result: " + future.get()); } executor.shutdown(); }}
以上代码创建了一个固定大小为5的线程池,提交了10个任务,并使用CompletionService获取已完成的任务的结果。每个任务会随机休眠一段时间,然后返回任务的编号。在主线程中,使用completionService.take()方法获取已完成的任务的结果,并输出任务的编号。
5、Callable和Future
Callable是Java中提供的一个接口,它类似于Runnable接口,但是可以返回执行结果。Future是Java中提供的一个接口,它可以用于获取异步执行任务的结果。
以下是一个使用Callable和Future的示例代码:
import java.util.concurrent.*;public class CallableAndFutureExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newSingleThreadExecutor(); Callable task = new Callable() { @Override public Integer call() throws Exception { Thread.sleep(1000); return 1 + 2; } }; Future future = executor.submit(task); System.out.println("Result: " + future.get()); executor.shutdown(); }}
以上代码创建了一个单线程的线程池,提交了一个任务,并使用Future获取任务的执行结果。任务会休眠1秒钟,然后返回1+2的结果。在主线程中,使用future.get()方法获取任务的执行结果,并输出结果。
6、Runnable和Thread
Runnable是Java中提供的一个接口,它表示一个可以被线程执行的任务。Thread是Java中提供的一个类,它表示一个线程。
以下是一个使用Runnable和Thread的示例代码:
public class RunnableAndThreadExample { public static void main(String[] args) throws InterruptedException { Runnable task = new Runnable() { @Override public void run() { System.out.println("Task executed by " + Thread.currentThread().getName()); } }; Thread thread = new Thread(task); thread.start(); thread.join(); }}
以上代码创建了一个任务,并使用Thread将任务提交到一个新的线程中执行。在主线程中,使用thread.join()方法等待新线程执行完毕。每个任务的执行会输出执行线程的名称。
7、总结
本文介绍了Java中常见的线程池实现,包括ForkJoinPool、Executors、CompletionService、Callable、Future、Runnable等知识点的详细讲解和完整可运行的代码示例。线程池是Java中常见的多线程编程方式,它可以有效地管理线程的创建、销毁和复用,从而提高程序的性能和稳定性。在实际开发中,需要根据具体的需求选择合适的线程池实现。
标签:
-
你真的了解ForkJoinPool吗?这些技巧让你的代码性能提升十倍!
-
【世界速看料】洞口:百人旁听 庭审现场变警示教育课堂
-
今日热闻!联明股份3涨停
-
焦点快报!郑州惠济区英才美寓附近有医院吗?附地址+电话
-
新动态:抵触全面电动化 日本汽车:过于自信还是加拉帕戈斯现象?
-
天天时讯:共建氢能源产业生态 未势能源与河钢集团全面深化战略合作
-
厦门农民工能享受失业保险待遇吗?如何申领一次性生活补助金?-全球新消息
-
北京市青少年冰球队参选人数创新高
-
【速看料】从九牧亮相上海国际厨卫展看中国品牌进击的三大关口
-
怎么打印电脑上的文件-怎么打印测试页
-
当前视点!人·车·生活完美融合,全新悍途宿营车正式上市,27.68万元起售
-
微宏快充加速武汉“氢装上阵”_微头条
-
天天热门:1 周岁小孩过生日送什呢礼物
-
环球动态:南通如皋:农忙季, 只闻“机”声不见人
-
韩国央行委员:不应排除进一步加息的可能性 观察
-
能链智电收购香港光电89.99%股权 世界百事通
-
佳创视讯:去年VR业务毛利下降主要因前期拍摄销售的内容成本摊销
-
彩蝶实业6月13日快速回调
-
当前热讯:狗子拆家铲求助大学生帮忙遛狗,没想到大学生一插手
-
【天天播资讯】9月07日更新消息 8月末我国外汇储备规模为30549亿美元