04-案例实现
案例实现
本节将实现一个任务来更新一组产品的价格。初始任务负责更新列表中的全部元素。由于需要设置参考大小为10,因此如果任务更新的元素超过10个,则将列表分割为两部分,并创建两个任务来更新各自部分的产品价格。
根据如下步骤来实现本案例:
1.创建一个名为 Product
的类,用来存储产品的名称和价格:
public class Product {
2.声明一个名为 name
的私有 String
型属性和一个名为 price
的私有 double
型属性:
private String name;
private double price;
3.实现这些属性的 getter
和 setter
方法。因为这些方法比较简单,所以不再给出源码。
4.创建一个名为 ProductListGenerator
的类,用来创建一个随机产品列表:
public class ProductListGenerator {
5.实现 generate()
方法。该方法接收一个代表列表大小的 int
型参数,并返回生成的 List<Product>
对象:
public List<Product> generate (int size) {
6.创建一个产品列表对象并将其返回:
List<Product> ret=new ArrayList<Product>();
7.生成一组产品,给全部产品赋值相同的价格(例如10),来验证程序是否运行正常:
for (int i=0; i<size; i++){
Product product=new Product();
product.setName("Product "+i);
product.setPrice(10);
ret.add(product);
}
return ret;
}
8.创建一个名为 Task
的类。声明其继承自 RecursiveAction
类:
public class Task extends RecursiveAction {
9.声明一个名为 products
的私有 List<Product>
属性:
private List<Product> products;
10.声明名为 first
和 last
的两个私有 int
型属性。这两个变量决定任务中产品的执行范围:
private int first;
private int last;
11.声明一个名为 increment
的私有 double
型属性,用来存储产品价格的涨幅:
private double increment;
12.实现该类的构造方法,初始化全部属性:
public Task (List<Product> products, int first, int last,
double increment) {
this.products=products;
this.first=first;
this.last=last;
this.increment=increment;
}
13.实现 compute()
方法。该方法实现了任务的逻辑部分:
@Override
protected void compute() {
14.如果 last
和 first
属性的差小于 10
,则用 updatePrices()
方法增加产品集合中的产品价格:
if (last - first<10) {
updatePrices();
15.如果 last
和 first
属性的差距大于等于10,则创建两个 Task
对象(一个用来执行前一半产品,另一个用来执行另一半产品)。在 ForkJoinPool
中调用 invokeAll()
方法来执行:
} else {
int middle=(last+first)/2;
System.out.printf("Task: Pending tasks:%s\n",
getQueuedTaskCount());
Task t1=new Task(products, first,middle+1, increment);
Task t2=new Task(products, middle+1,last, increment);
invokeAll(t1, t2);
}
16.实现 updatePrices()
方法。该方法更新列表中下标处于 first
和 last
属性之间的产品:
private void updatePrices() {
for (int i=first; i<last; i++){
Product product=products.get(i);
product.setPrice(product.getPrice()*(1+increment));
}
}
17.至此,就可以开始实现应用程序的入口,创建一个名为 Main
的类并为其添加 main()
方法:
public class Main {
public static void main(String[] args) {
18.用 ProductListGenerator
类创建一个包含10000个产品的列表:
ProductListGenerator generator = new ProductListGenerator();
List<Product> products=generator.generate(10000);
19.创建一个新的 Task
对象来更新列表中所有产品的价格。参数 first
的值为0,参数 last
的值为10000( products列
表长度):
Task task=new Task(products, 0, products.size(), 0.20);
20.用无参构造方法创建一个 ForkJoinPool
对象:
ForkJoinPool pool=new ForkJoinPool();
21.在池中用 execute()
方法执行任务:
pool.execute(task);
22.实现一个代码块,每5ms显示一次池中信息,在任务执行结束前打印池中参数值:
do {
System.out.printf("Main: Thread Count:%d\n",
pool.getActiveThreadCount());
System.out.printf("Main: Thread Steal:%d\n",
pool.getStealCount());
System.out.printf("Main: Parallelism:%d\n",
pool.getParallelism());
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (!task.isDone());
23.调用 shutdown()
方法关闭池:
pool.shutdown();
24.用 isCompletedNormally()
方法来检查本例中的任务是否正常执行完毕,并打印日志:
if (task.isCompletedNormally()){
System.out.printf("Main: The process has completed
normally.\n");
}
25.产品的预期价格为12,打印出所有价格不为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());
}
}
26.打印信息来表明程序运行结束:
System.out.println("Main: End of the program.\n");