Skip to content
Advertisement

How to set the Thread priority on parallel iteration with standard Java API?

I found in this tutorial a way to iterate in parallel a collection of objects by setting threads priority, but this example uses the Burningwave Core library: is there a way to do the same with the standard Java API?

I found in this tutorial a way to iterate in parallel a collection of objects by setting threads priority, but this example uses the Burningwave Core library: is there a way to do the same with the standard Java API?

Here the code of the tutorial:

import static org.burningwave.core.assembler.StaticComponentContainer.IterableObjectHelper;
import static org.burningwave.core.assembler.StaticComponentContainer.ManagedLoggerRepository;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.burningwave.core.iterable.IterableObjectHelper.IterationConfig;

public class CollectionAndArrayIterator {

    public static void execute() {
        List<String> output = IterableObjectHelper.iterateAndGet(
            IterationConfig.of(buildCollection())
            //Enabling parallel iteration when the input collection size is greater than 2
            .parallelIf(inputColl -> inputColl.size() > 2)
            //Setting threads priority
            .withPriority(Thread.MAX_PRIORITY)
            //Setting up the output collection
            .withOutput(new ArrayList<String>())
            .withAction((number, outputCollectionSupplier) -> {
                if (number > 500000) {
                    //Terminating the current thread iteration early.
                    IterableObjectHelper.terminateCurrentThreadIteration();
                    //If you need to terminate all threads iteration (useful for a find first iteration) use
                    //IterableObjectHelper.terminateIteration();
                }
                if ((number % 2) == 0) {                        
                    outputCollectionSupplier.accept(outputCollection ->
                        //Converting and adding item to output collection
                        outputCollection.add(number.toString())
                    );
                }
            })    
        );
        
        IterableObjectHelper.iterate(
            IterationConfig.of(output)
            //Disabling parallel iteration
            .parallelIf(inputColl -> false)
            .withAction((number) -> {
                ManagedLoggerRepository.logInfo(CollectionAndArrayIterator.class::getName, "Iterated number: {}", number);
            })    
        );
        
        ManagedLoggerRepository.logInfo(
            CollectionAndArrayIterator.class::getName,
            "Output collection size {}", output.size()
        );
    }

    private static Collection<Integer> buildCollection() {
        Collection<Integer> inputCollection = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            inputCollection.add(i);
        }
        return inputCollection;
    }
    
    public static void main(String[] args) {
        execute();
    }
    
}

Advertisement

Answer

Referring to the answer from Custom thread pool in Java 8 parallel stream You can use List.parallelStream with a Custom ForkJoinPool. The trick is fill up the pool with a custom ForkJoinWorkerThreadFactory that sets required priority to threads.

  1. Create a custom ForkJoinWorkerThreadFactory that sets the required thread priority.
  2. Create a ForkJoinPool by passing this factory in constructor.
  3. Submit the parallel stream task as explained in the above mentioned answer.
List<Integer> list = getList();
    
ForkJoinWorkerThreadFactory factory = pool -> {
    ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
    worker.setPriority(5);
    return worker;
};
    
ForkJoinPool pool = new ForkJoinPool(4, factory, null, true);
int sum = pool.submit(() -> list.parallelStream().reduce(0, Integer::sum)).join();
System.out.println("sum: " + sum);   
Advertisement