Optimizing CPU usage by performing tasks in parallel with different priorities in Java

Tutorials (13 Part Series)

1 How to create your own dependency injection framework in Java
2 How to find all the classes of a package in Java
9 more parts…
3 How to get field values with Reflection and with direct memory access in Java
4 Optimizing CPU usage by performing tasks in parallel with different priorities in Java
5 How to bind methods or constructors to functional interfaces in Java
6 Generating classes at runtime and invoking their methods with and without the use of Reflection in Java
7 A fast and flexible way to scan the class paths in Java
8 Executing stringified source code in Java
9 How to scan the file system in Java
10 Invoking and handling privates and all other methods of an object with and without the use of Reflection in Java
11 Making applications created with old Java versions work on Java 9 and later versions
12 How to generate and compile sources at runtime in Java
13 Iterating collections and arrays in parallel by setting thread priority

A small limitation of Java CompletableFuture is the inability to choose the priority of the thread they are assigned to, thus making it impossible to assign the desired workload to the cpu.

In this situation, the BackgroundExecutor component of Burningwave Core library comes to our aid, by giving us the ability to launch different functional interfaces in parallel by setting the priority of the thread they will be assigned. There is also the option to wait for them start or finish. This component is also used by the IterableObjectHelper component to iterate collections or arrays in parallel.

To use the BackgroundExecutor you should simply add the following to your projects dependencies:

For obtaining threads the BackgroundExecutor uses the ThreadSupplier component which can be configured in the
burningwave.static.properties file through the following properties:

thread-supplier.default-daemon-flag-value=true
thread-supplier.default-thread-priority=5
thread-supplier.max-detached-thread-count=${thread-supplier.max-poolable-thread-count}
thread-supplier.max-detached-thread-count.elapsed-time-threshold-from-last-increase-for-gradual-decreasing-to-initial-value=30000
thread-supplier.max-detached-thread-count.increasing-step=autodetect
thread-supplier.max-poolable-thread-count=autodetect
thread-supplier.poolable-thread-request-timeout=6000

Enter fullscreen mode Exit fullscreen mode

The ThreadSupplier provides a fixed number of reusable threads indicated by the thread-supplier.max-poolable-thread-count property and, if these threads have already been assigned, new non-reusable threads will be created whose quantity maximum is indicated by the thread-supplier.max-detached-thread-count property. Once this limit is reached if the request for a new thread exceeds the waiting time indicated by the thread-supplier.poolable-thread-request-timeout property, the ThreadSupplier will proceed to increase the limit indicated by the thread-supplier.max-detached-thread-count property for the quantity indicated by the thread-supplier.max-detached-thread-count.increasing-step property. Resetting the thread-supplier.max-detached-thread-count property to its initial value, will occur gradually only when there have been no more waits on thread requests for an amount of time indicated by the thread-supplier.max-detached-thread-count.elapsed-time-threshold-from-last-increase-for-gradual-decreasing-to-initial-value property.

Let’s see now an example on how to create tasks:

import static org.burningwave.core.assembler.StaticComponentContainer.BackgroundExecutor;

import org.burningwave.core.ManagedLogger;
import org.burningwave.core.concurrent.QueuedTasksExecutor.ProducerTask;
import org.burningwave.core.concurrent.QueuedTasksExecutor.Task;


public class TaskLauncher implements ManagedLogger {

    public void launch() {
        ProducerTask<Long> taskOne = BackgroundExecutor.createProducerTask(task -> {
            Long startTime = System.currentTimeMillis();
            logInfo("task one started");
            synchronized (this) {                
                wait(5000);
            }
            Task internalTask = BackgroundExecutor.createTask(tsk -> {
                logInfo("internal task started");    
                synchronized (this) {                
                    wait(5000);
                }
                logInfo("internal task finished");    
            }, Thread.MAX_PRIORITY).submit();
            internalTask.waitForFinish();
            logInfo("task one finished");
            return startTime;
        }, Thread.MAX_PRIORITY);
        taskOne.submit();
        Task taskTwo = BackgroundExecutor.createTask(task -> {
            logInfo("task two started and wait for task one finishing");
            taskOne.waitForFinish();
            logInfo("task two finished");    
        }, Thread.NORM_PRIORITY);
        taskTwo.submit();
        ProducerTask<Long> taskThree = BackgroundExecutor.createProducerTask(task -> {
            logInfo("task three started and wait for task two finishing");
            taskTwo.waitForFinish();
            logInfo("task two finished");
            return System.currentTimeMillis();
        }, Thread.MIN_PRIORITY);
        taskThree.submit();
        taskThree.waitForFinish();
        logInfo("Elapsed time: {}ms", taskThree.join() - taskOne.join());
    }

    public static void main(String[] args) {
        new TaskLauncher().launch();
    }

}

Enter fullscreen mode Exit fullscreen mode

Tutorials (13 Part Series)

1 How to create your own dependency injection framework in Java
2 How to find all the classes of a package in Java
9 more parts…
3 How to get field values with Reflection and with direct memory access in Java
4 Optimizing CPU usage by performing tasks in parallel with different priorities in Java
5 How to bind methods or constructors to functional interfaces in Java
6 Generating classes at runtime and invoking their methods with and without the use of Reflection in Java
7 A fast and flexible way to scan the class paths in Java
8 Executing stringified source code in Java
9 How to scan the file system in Java
10 Invoking and handling privates and all other methods of an object with and without the use of Reflection in Java
11 Making applications created with old Java versions work on Java 9 and later versions
12 How to generate and compile sources at runtime in Java
13 Iterating collections and arrays in parallel by setting thread priority

原文链接:Optimizing CPU usage by performing tasks in parallel with different priorities in Java

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容