Resumen de aprendizaje de CompletionService

Introducción a CompletionService

CompletionService integra las funciones de Executor y BlockingQueue , envía las tareas invocables a CompletionService para su ejecución y luego usa métodos como take y poll similares a las operaciones de cola para obtener los resultados completos, y estos resultados se encapsularán como Future cuando se completen .

CompletionServicePara lograr una disociación del acceso del productor y del consumidor a los resultados sometidos a la tarea, tanto los productores como los consumidores no se preocupan por el pedido para completar la tarea CompletionServicepara garantizar que los consumidores deben estar de acuerdo con el pedido para completar la tarea para obtener los resultados. Con esta función, podemos lograr fácilmente el orden del procesamiento posterior y evitar esperas innecesarias.

Además, CompletionService es una interfaz y no se puede usar directamente. Por lo general, usa su clase de implementación ExecutorCompletionService

Escenarios de aplicación

El escenario de la solución principal es que el hilo principal envía múltiples tareas y luego espera procesar los resultados cuando se completan las tareas, y procesarlas una por una en el orden de finalización de las tareas (por ejemplo, si las solicitudes concurrentes regresan para actualizar la interfaz de usuario, puede comenzar a cepillar si la solicitud es exitosa sin esperar a que todo esté bien Solo cepíllate y espera)

Método común

  1. Envío futuro (Callabletask);

enviar se usa para enviar un objeto invocable, que se usa para enviar una tarea de subproceso que puede obtener resultados

  1. Envío futuro (tarea ejecutable, resultado V);

submit se utiliza para enviar un objeto Runnable y un objeto de resultado, similar al submit anterior, pero el valor de retorno de runnable void no puede obtener el resultado del hilo, por lo que el resultado se agrega como un puente de parámetro

  1. Future take () lanza InterruptedException;

take se usa para sacar el último resultado de ejecución del hilo, tenga en cuenta que está bloqueado aquí hasta que se pueda obtener la tarea

  1. Encuesta futura ();

take se usa para sacar el último resultado de ejecución del hilo, no es bloqueante y devuelve nulo si no hay resultado

  1. La encuesta futura (tiempo de espera prolongado, unidad TimeUnit) arroja InterruptedException;

Obtención del método de tarea con tiempo de espera de espera

Caso de aplicación: consultar 3 sitios web y resumir los resultados

package com.example.demo.juc;

import cn.hutool.core.thread.ThreadUtil;
import com.google.common.collect.Lists;

import java.util.List;
import java.util.concurrent.*;

/**
 * @Author shangkaihui
 * @Date 2020/8/13 09:44
 * @Desc
 */
public class CompletionServiceDemo {
    
    

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        // 查询信息
        String queryName = "java";
        // 调用查询接口
        long startTime = System.currentTimeMillis();
        queryInfoCode3(queryName);
        System.out.println("耗时: " + (System.currentTimeMillis() - startTime));
    }

    /**
     * 串行聚合查询信息 code 1
     *
     * @param queryName
     * @return
     */
    private static List<String> queryInfoCode1(String queryName) {
    
    
        List<String> resultList = Lists.newArrayList();

        String webA = searchWebA(queryName);
        resultList.add(webA);

        String webB = searchWebB(queryName);
        resultList.add(webB);

        String webC = searchWebC(queryName);
        resultList.add(webC);

        return resultList;
    }

    /**
     * 使用多线程future并行聚合查询信息,任务完成时间取决于耗时最长的任务
     *
     * @param queryName
     * @return
     */
    private static List<String> queryInfoCode2(String queryName) throws ExecutionException, InterruptedException {
    
    
        List<String> resultList = Lists.newArrayList();

        // 创建3个线程的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        try {
    
    
            // 创建任务的 feature
            Future<String> webAFuture = pool.submit(() -> searchWebA(queryName));
            Future<String> webBFuture = pool.submit(() -> searchWebB(queryName));
            Future<String> webCFuture = pool.submit(() -> searchWebC(queryName));
            // 得到任务结果
            resultList.add(webAFuture.get());
            resultList.add(webBFuture.get());
            resultList.add(webCFuture.get());
        } finally {
    
    
            // 关闭线程池
            pool.shutdown();
        }

        return resultList;
    }

    /**
     * 使用CompletionService完成聚合查询信息,先完成的任务先返回
     *
     * @param queryName
     * @return
     */
    private static void queryInfoCode3(String queryName) throws ExecutionException, InterruptedException {
    
    
        // 开始时间
        long startTime = System.currentTimeMillis();
        // 创建 CompletionService
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        CompletionService executorCompletionService = new ExecutorCompletionService(executorService);

        // 创建任务的 feature
        executorCompletionService.submit(() -> searchWebA(queryName));
        executorCompletionService.submit(() -> searchWebB(queryName));
        executorCompletionService.submit(() -> searchWebC(queryName));

        for (int i = 0; i < 3; i++) {
    
    
            Future take = executorCompletionService.take();
            System.out.println("获得请求结果 -> " + take.get());
            System.out.println("通过 ws 推送给客户端,总共耗时" + (System.currentTimeMillis() - startTime));
        }

        executorService.shutdown();
    }

    /**
     * 查询网站 A
     *
     * @param name
     * @return
     */
    public static String searchWebA(String name) {
    
    
        ThreadUtil.sleep(5000);
        return "webA";
    }

    /**
     * 查询网站B
     *
     * @param name
     * @return
     */
    public static String searchWebB(String name) {
    
    
        ThreadUtil.sleep(3000);
        return "webB";
    }

    /**
     * 查询网站C
     *
     * @param name
     * @return
     */
    public static String searchWebC(String name) {
    
    
        ThreadUtil.sleep(500);
        return "webC";
    }
}

Supongo que te gusta

Origin blog.csdn.net/kaihuishang666/article/details/107974168
Recomendado
Clasificación