How to do it...

In this recipe, you are going to implement a task to update the price of a list of products. The initial task will be responsible for updating all the elements in a list. You will use a size 10 as the reference size, so if a task has to update more than 10 elements, it divides the part of the list assigned to it in two parts and creates two tasks to update the prices of the products in the respective parts.

Follow these steps to implement the example:

  1. Create a class named Product that will store the name and price of a product:
        public class Product { 
  1. Declare a private String attribute named name and a private double attribute named price:
        private String name; 
private double price;
  1. Implement getter and setter methods for those fields. They are very simple to implement, so its source code is not included.
  2. Create a class named ProductListGenerator to generate a list of random products:
        public class ProductListGenerator { 
  1. Implement the generate() method. It receives an int parameter with the size of the list and returns a List<Product> object with the list of generated products:
        public List<Product> generate (int size) { 
  1. Create the object to return the list of products:
        List<Product> ret=new ArrayList<Product>(); 
  1. Generate the list of products. Assign the same price to all of the products, for example, 10, to check that the program works well:
          for (int i=0; i<size; i++){ 
Product product=new Product();
product.setName("Product "+i);
product.setPrice(10);
ret.add(product);
}
return ret;
}
  1. Create a class named Task. Specify that it extends the RecursiveAction class:
        public class Task extends RecursiveAction { 
  1. Declare a private List<Product> attribute named products:
        private List<Product> products; 
  1. Declare two private int attributes named first and last. These attributes will determine the block of products this task has to process:
        private int first; 
private int last;
  1. Declare a private double attribute named increment to store the increment of the price of the products:
        private double increment; 
  1. Implement the constructor of the class that will initialize all the attributes of the class:
        public Task (List<Product> products, int first, int last,
double increment) {
this.products=products;
this.first=first;
this.last=last;
this.increment=increment;
}
  1. Implement the compute() method, which will implement the logic of the task:
        @Override 
protected void compute() {
  1. If the difference of the last and first attributes is less than 10 (the task has to update the price of less than 10 products), increment the price of that set of products using the updatePrices() method:
        if (last - first<10) { 
updatePrices();
  1. If the difference between the last and first attributes is greater than or equal to 10, create two new Task objects, one to process the first half of the products and the other to process the second half, and execute them in ForkJoinPool using the invokeAll() method:
        } else { 
int middle=(last+first)/2;
System.out.printf("Task: Pending tasks:%s ",
getQueuedTaskCount());
Task t1=new Task(products, first,middle+1, increment);
Task t2=new Task(products, middle+1,last, increment);
invokeAll(t1, t2);
}
  1. Implement the updatePrices() method. This method updates the products that occupy the positions between the values of the first and last attributes in the list of products:
        private void updatePrices() { 
for (int i=first; i<last; i++){
Product product=products.get(i);
product.setPrice(product.getPrice()*(1+increment));
}
}
  1. Implement the main class of the example by creating a class named Main and add the main() method to it:
        public class Main { 
public static void main(String[] args) {
  1. Create a list of 10000 products using the ProductListGenerator class:
        ProductListGenerator generator=new ProductListGenerator(); 
List<Product> products=generator.generate(10000);
  1. Create a new Task object to update the prices of all the products in the list. The parameter first takes the value 0 and the last parameter takes the value 10000 (the size of the product list):
        Task task=new Task(products, 0, products.size(), 0.20); 
  1. Create a ForkJoinPool object using the constructor without parameters:
        ForkJoinPool pool=new ForkJoinPool(); 
  1. Execute the task in the pool using the execute() method:
        pool.execute(task); 
  1. Implement a block of code that shows information about the evolution of the pool every five milliseconds, writing to the console the value of some parameters of the pool until the task finishes its execution:
        do { 
System.out.printf("Main: Thread Count:%d ",
pool.getActiveThreadCount());
System.out.printf("Main: Thread Steal:%d ",
pool.getStealCount());
System.out.printf("Main: Parallelism:%d ",
pool.getParallelism());
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (!task.isDone());
  1. Shut down the pool using the shutdown() method:
        pool.shutdown(); 
  1. Check if the task has finished without errors with the isCompletedNormally() method and in that case, write a message to the console:
        if (task.isCompletedNormally()){ 
System.out.printf("Main: The process has completed
normally. ");
}
  1. The expected price of all the products, after the increment, is 12. Write the name and price of all the products that have a price difference of 12 to check that all of them have increased their price correctly:
        for (int i=0; i<products.size(); i++){ 
Product product=products.get(i);
if (product.getPrice()!=12) {
System.out.printf("Product %s: %f ",
product.getName(),product.getPrice());
}
}
  1. Write a message to indicate the finalization of the program:
        System.out.println("Main: End of the program.
"); 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.205.228