一、使用Fork/Join的步骤
1、创建用来执行任务的ForkJoinPool对象
2、创建即将在线程池中被执行的任务ForkJoinTask子类/或者ForkJoinAction子类
3、实现上述子类的compute方法,对任务的分解
4、调用ForkJoinPool对象的execute()方法执行任务
1、Fork/Join---invokeAll()方法用来执行一个主任务所创建的子任务。这是一个同步调用。这个任务将等待子任务完成,然后继续执行或者结束
2、当一个主任务等待它的子任务时,执行这个主任务的工作者线程接收另一个等待执行的任务并开始执行,这就是Fork/Join框架比Runnable和Callable对象更加高效的原因
3、执行器框架的invokeAll()方法,必须将任务发送给执行器,Fork/Join中,任务的控制是在线程池中进行的
4、invoke()方法:这个方法是同步调用的,必须等到传进来的任务执行完毕才会返回
5、execute()方法:这个方法是异步调用的
三、模拟对商品价格的修改
package com.currency.forkandjoin; /** * 产品类,用来存储产品的名称和价格 * * @author Nicholas * */ public class Product { private String name; private double price; public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
package com.currency.forkandjoin; import java.util.ArrayList; import java.util.List; /** * 用来生成随机产品列表 * * @author Nicholas * */ public class ProductListGenerator { public List
generateProducts(int size) { List products = new ArrayList (); for (int i = 0; i < size; i++) { Product product = new Product(); product.setName("Product-" + i); product.setPrice(10); products.add(product); } return products; } }
package com.currency.forkandjoin; import java.util.List; import java.util.concurrent.RecursiveAction; /** * 实现对产品的价格的更改 * @author Nicholas * */ public class Task extends RecursiveAction { /** * */ private static final long serialVersionUID = 1L; private List
products; private int first; private int last; private double increment; public Task(List products, int first, int last, double increment) { this.products = products; this.first = first; this.last = last; this.increment = increment; } @Override protected void compute() { //一次任务只能更新少于10个产品的价格 if (last - first < 10) updatePrice(); else { int middle = (last + first) / 2; System.out.println("Pending task :" + getQueuedTaskCount()); Task task1 = new Task(products, first, middle + 1, increment); Task task2 = new Task(products, middle + 1, last, increment); invokeAll(task1, task2); } } /** * 更新处于first和last之间的产品的价格 */ public void updatePrice() { for (int i = first; i < last; i++) { Product product = products.get(i); product.setPrice(product.getPrice() * (1 + increment)); } } }
package com.currency.forkandjoin; import java.util.List; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; public class Main { public void testTask() { ProductListGenerator productListGenerator = new ProductListGenerator(); // 生成10000个产品 List
products = productListGenerator.generateProducts(10000); Task task = new Task(products, 0, products.size(), 0.20); // 创建ForkJoin对象 ForkJoinPool forkJoinPool = new ForkJoinPool(); // 调用execute()方法执行任务 forkJoinPool.execute(task); // 打印线程池的演变过程 do { System.out.printf("Main : Thread Count : %d\n", forkJoinPool.getActiveThreadCount()); System.out.printf("Main : Thread Steal : %d\n", forkJoinPool.getStealCount()); System.out.printf("Main : Thread Parallelism : %d\n", forkJoinPool.getParallelism()); // 每隔5ms,打印参数值 try { TimeUnit.MILLISECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } while (!task.isDone()); forkJoinPool.shutdown(); if (task.isCompletedNormally()) { System.out.println("Task is Completed Normally ..."); } // 更新之后,所有的产品的期望价格是12元 for (int i = 0; i < products.size(); i++) { Product product = products.get(i); if (product.getPrice() != 12) { System.out.printf("Product %s : %f\n", product.getName(), product.getPrice()); } } System.out.println("Main : End of the Program ..."); } public static void main(String[] args) { new Main().testTask(); } }