Java线程的学习_线程池
来源:互联网 发布:js 双重级联 编辑:程序博客网 时间:2024/06/05 18:59
系统启动一个新线程需要很高的成本,因为它涉及与操作系统交互。在这种情况下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时。
线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个线程来run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run()或call()方法。除此之外,使用线程池可以有效地控制系统中并发线程的数量。
使用Executors类来创建线程池:
使用线程池来执行线程任务的步骤:
1.调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池。
2.创建Runnable实现类或Callable实现类的实例,作为线程执行任务。
3.调用ExecutorService对象的submit()方法来提交Runnable实例或Callable实例。
4.当不想提交任何任务时,调用ExecutorService对象的shutdown()方法来关闭线程池。
使用线程池来执行指定Runnable对象所代表的的任务:
public class ThreadPoolTest { public static void main(String[] args)throws Exception{ //创建一个具有固定线程数(6)的线程池 ExecutorService pool = Executors.newFixedThreadPool(6); //使用Lambda表达式创建Runnable对象 Runnable target = () -> { for(int i = 0; i < 100; i++){ System.out.println(Thread.currentThread().getName() + "的i值为:" + i); } }; //向线程池中提交两个线程 pool.submit(target); pool.submit(target); //关闭线程池 pool.shutdown(); }}
ForkJoinPool类
ForkJoinPool类的作用是将一个任务拆分为多个“小任务”并行计算,再把多个“小任务”的结果合并成总的计算结果。ForkJoinPool类是ExecutorService的实现类,因此是一种特殊的线程池。
创建了ForkJoinPool实例之后,就可调用ForkJoinPool的submit(ForkJoinTask task)或invoke(ForkJoinTask task)方法来执行指定任务。其中ForkJoinTask代表一个可以并行、合并的任务。ForkJoinTask是一个抽象类,它还有两个抽象子类:RecursiveAction(没有返回值)和RecursiveTask(有返回值)。
没有返回值的“大任务”拆分:
//继承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(int i = 0; i < end; i++){ System.out.println(Thread.currentThread().getName() + "的i值:" + i); } }else{ //当end与start之间的差大于THRESHOLD时,开始打印 //将大任务分解成两个“小任务” int middle = (start + end) / 2; PrintTask left = new PrintTask(start, middle); PrintTask right = new PrintTask(middle, end); //并执行两个“小任务” left.fork(); right.fork(); } }}public class ForkJoinPoolTest { public static void main(String[] args)throws Exception{ ForkJoinPool pool = new ForkJoinPool(); //提交可分解的PrintTask任务 pool.submit(new PrintTask(0, 300)); pool.awaitTermination(2, TimeUnit.SECONDS); //关闭线程池 pool.shutdown(); }}
有返回值的“大任务”:
//继承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(int i = start; i < end; i++){ sum += arr[i]; } return sum; }else{ //当end与start之间的差大于THRESHOLD,既要累加的数超过20个时,将大任务分解成两个小任务 int middle = (start + end) / 2; CalTask left = new CalTask(arr, start, middle); CalTask 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{ int[] arr = new int[100]; Random rand = new Random(); int total = 0; //初始化100个数字元素 for(int i = 0, len = arr.length; i < len; i++){ int tmp = rand.nextInt(20); //对数组元素赋值,并将数组元素的值添加到sum总和中 System.out.println(tmp); total += (arr[i] = tmp); } System.out.println("初始化统计出的和:" + total); //创建一个通用池 ForkJoinPool pool = ForkJoinPool.commonPool(); //提交可分解的CaltTask任务 Future<Integer> future = pool.submit(new CalTask(arr, 0, arr.length)); System.out.println("使用CalTask计算出的和:" + future.get()); //关闭线程 pool.shutdown(); }}
- Java线程的学习_线程池
- Java线程的学习_线程同步
- Java线程的学习_线程通信
- Java线程的学习_线程组
- Java线程的学习_线程的创建和启动
- Java线程的学习_线程的生命周期
- Java线程的学习_线程的控制
- Java线程的学习_线程与集合
- Java学习笔记_线程池
- java学习笔记_线程
- Java线程_(一)线程的写法
- Java基础第十二天学习日记_线程、线程的同步、线程间通讯
- [java]_[线程池的使用]
- Java线程_(三)线程池
- java线程池的学习
- Java线程_线程调度之线程池
- 第三天,Java基础学习_线程
- java学习初探十八之线程的线程同步_锁机制_synchronized
- 2、React-Native项目调试
- [Xcode Tips]解决Xcode多个模拟器问题
- 【三】Gradle 基础知识学习笔记
- Tomcat的目录结构
- php源码之字符串与二进制相互转换
- Java线程的学习_线程池
- 编写jquery插件
- Android RecyclerView工作原理分析(下)
- 利用mfc动态画圆(已知圆心坐标,半径,以及每次转过的角度)
- 类似队列的java实现
- Android Studio 2.2 中几个实用的新功能
- C#中new的几种用法
- string::getline VS stream::getline
- 排序算法之 冒泡排序算法(Bubble Sort):(Python)