当前位置:嗨网首页>书籍在线阅读

04-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

本节将实现一个任务来更新一组产品的价格。初始任务负责更新列表中的全部元素。由于需要设置参考大小为10,因此如果任务更新的元素超过10个,则将列表分割为两部分,并创建两个任务来更新各自部分的产品价格。

根据如下步骤来实现本案例:

1.创建一个名为 Product 的类,用来存储产品的名称和价格:

public class Product {

2.声明一个名为 name 的私有 String 型属性和一个名为 price 的私有 double 型属性:

private String name;
private double price;

3.实现这些属性的 gettersetter 方法。因为这些方法比较简单,所以不再给出源码。

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.声明名为 firstlast 的两个私有 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.如果 lastfirst 属性的差小于 10 ,则用 updatePrices() 方法增加产品集合中的产品价格:

if (last - first<10) {
  updatePrices();

15.如果 lastfirst 属性的差距大于等于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() 方法。该方法更新列表中下标处于 firstlast 属性之间的产品:

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");