Analyse de l'utilisation et du principe de Fork/Join

1. Qu'est-ce que ForkJoin

Java 7 a commencé à introduire un nouveau pool de threads Fork/Join, qui peut diviser une grande tâche en plusieurs petites tâches pour une exécution parallèle, puis agréger les résultats d'exécution de chaque petite tâche pour obtenir le résultat final de la grande tâche.

Le principe de la tâche Fork/Join : déterminer si une tâche est suffisamment petite, et si elle est suffisamment petite, la calculer directement, sinon, la scinder en plusieurs petites tâches à calculer séparément.

fork():在当前线程运行的线程池中创建一个子任务;
join():模块子任务完成的时候返回任务结果;
insérez la description de l'image ici

2. Vol d'emploi

Les grandes tâches sont divisées en sous-tâches indépendantes, et les sous-tâches sont placées dans différentes files d'attente, et un thread est créé pour chaque file d'attente pour exécuter les tâches dans la file d'attente, en supposant que le thread B exécute d'abord les tâches affectées à sa propre file d'attente. temps, s'il y a des tâches en attente d'exécution dans la file d'attente correspondant au thread, le thread inactif B volera l'exécution de la tâche dans la file d'attente du thread A, et afin de réduire la concurrence entre le thread B et le thread de tâche volé A lors du vol de tâches, le thread de vol de tâches B obtiendra l'exécution de la tâche à partir de la queue de la file d'attente, et le thread de tâche volé A obtiendra l'exécution de la tâche à partir de la tête de la file d'attente.
insérez la description de l'image ici

3. Exemples d'applications

Trouver la somme de 1~10000

//传统思维
public static void main(String[] args) {
    
    
    int sum = 0;
    long start = System.currentTimeMillis();
    for (long i = 0; i < 100000000L; i++) {
    
    
        sum += i;
    }
    long end = System.currentTimeMillis();
    System.out.println(end-start);
}

L'utilisation de ForkJoin est effectuée par ForkJoinPool (utilisé uniquement lorsque la quantité de données est importante)
insérez la description de l'image ici

public class ForkJoinTest {
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        long start = System.currentTimeMillis();

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinDemo(1L, 100000000L);
        //提交任务
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);
        Long sum = submit.get();

        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
}

public class ForkJoinDemo extends RecursiveTask<Long> {
    
    

    private Long start = 1L;
    private Long end = 100000000L;

    //临界值
    private Long temp = 10000L;

    public ForkJoinDemo(Long start, Long end) {
    
    
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
    
    
        if ((end - start) < temp) {
    
    
            // 基本运算
            Long sum = 0L;
            for (Long i = start; i <= end; i++) {
    
    
                sum += i;
            }
            return sum;
        }else {
    
    
            // ForkJoin
            Long middle = (start + end)/2;
            // 把一个大任务拆分成两个小任务
            ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
            // 把任务压入线程队列
            task1.fork();
            ForkJoinDemo task2 = new ForkJoinDemo(middle+1, end);
            task2.fork();
            return task1.join()+task2.join();
        }
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/myjess/article/details/121377597
conseillé
Classement