Análisis del uso y principio de Fork/Join

1. ¿Qué es ForkJoin?

Java 7 comenzó a introducir un nuevo grupo de subprocesos Fork/Join, que puede dividir una tarea grande en múltiples tareas pequeñas para ejecución paralela y luego agregar los resultados de ejecución de cada tarea pequeña para obtener el resultado final de la tarea grande.

El principio de la tarea Fork/Join: determinar si una tarea es lo suficientemente pequeña y, si es lo suficientemente pequeña, calcularla directamente; de ​​lo contrario, dividirla en varias tareas pequeñas para calcularlas por separado.

fork():在当前线程运行的线程池中创建一个子任务;
join():模块子任务完成的时候返回任务结果;
inserte la descripción de la imagen aquí

2. Robo de empleo

Las tareas grandes se dividen en subtareas independientes, y las subtareas se colocan en diferentes colas, y se crea un subproceso para cada cola para ejecutar las tareas en la cola, asumiendo que el subproceso B ejecuta primero las tareas asignadas a su propia cola. tiempo, si hay tareas esperando para ser ejecutadas en la cola correspondiente al subproceso, el subproceso inactivo B robará la ejecución de la tarea en la cola del subproceso A, y con el fin de reducir la competencia entre el subproceso B y la tarea robada subproceso A al robar tareas, robar tareas El subproceso B obtendrá la ejecución de la tarea desde el final de la cola, y el subproceso A de la tarea robada obtendrá la ejecución de la tarea desde el principio de la cola.
inserte la descripción de la imagen aquí

3. Ejemplos de aplicación

Encuentra la suma 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);
}

El uso de ForkJoin lo realiza ForkJoinPool (solo se usa cuando la cantidad de datos es grande)
inserte la descripción de la imagen aquí

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();
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/myjess/article/details/121377597
Recomendado
Clasificación