Java 线程池多任务先完成先返回处理结果

范例1:线程池多任务先完成先返回处理结果

package com.contoso;

import java.util.Random;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CompletionServiceExample1 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Random random = new Random();
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        // CompletionService内部实现使用了blockingQueue>存储已经完成任务的执行结果
        CompletionService service = new ExecutorCompletionService(executorService);

        for (int i = 1; i <= 10; i++) {
            final int index = i;
            service.submit(() -> {
                long start = System.nanoTime();
                Thread.sleep(random.nextInt(5000));
                System.out.println(Thread.currentThread().getName() + "|任务正在处理中 ...");
                long end = System.nanoTime();
                double timeTaken = (end - start) / 1e9;
                return String.valueOf(Thread.currentThread().getName() + " Task" + index + " Taken in seconds:" + timeTaken);
            });
        }

        for (int j = 1; j <= 10; j++) {
            long start = System.nanoTime();
            //没有完成的任务在这一行代码这里会出现阻塞,耗时最少任务的处理结果先从take里面出来
            Future take = service.take();
            long end = System.nanoTime();
            double timeTaken = (end - start) / 1e9;
            System.out.println("主线程打印没有完成的任务被阻塞的时间(单位:秒)" + timeTaken);

            String result = take.get(); // 这一行代码在这里不会阻塞,引入放入队列中的都是已经完成的任务
            System.out.println("主线程打印返回任务的处理时间:" + result + "\n");
        }
        executorService.shutdown();
        System.out.println("所有任务已经完成,关闭线程池");
    }
}
run:
pool-1-thread-5|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.126341778
主线程打印返回任务的处理时间:pool-1-thread-5 Task5 Taken in seconds:0.12415651

pool-1-thread-1|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)1.199077737
主线程打印返回任务的处理时间:pool-1-thread-1 Task1 Taken in seconds:1.325494439

pool-1-thread-7|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)1.073619992
主线程打印返回任务的处理时间:pool-1-thread-7 Task7 Taken in seconds:2.39895914

pool-1-thread-6|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.027563512
主线程打印返回任务的处理时间:pool-1-thread-6 Task6 Taken in seconds:2.426902391

pool-1-thread-2|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.494719977
主线程打印返回任务的处理时间:pool-1-thread-2 Task2 Taken in seconds:2.921960165

pool-1-thread-4|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.538435259
主线程打印返回任务的处理时间:pool-1-thread-4 Task4 Taken in seconds:3.46030321

pool-1-thread-8|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.201699418
主线程打印返回任务的处理时间:pool-1-thread-8 Task8 Taken in seconds:3.661973811

pool-1-thread-3|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.012382544
主线程打印返回任务的处理时间:pool-1-thread-3 Task3 Taken in seconds:3.674586569

pool-1-thread-9|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.767456447
主线程打印返回任务的处理时间:pool-1-thread-9 Task9 Taken in seconds:4.442219117

pool-1-thread-10|任务正在处理中 ...
主线程打印没有完成的任务被阻塞的时间(单位:秒)0.015987835
主线程打印返回任务的处理时间:pool-1-thread-10 Task10 Taken in seconds:4.458432685

所有任务已经完成,关闭线程池
BUILD SUCCESSFUL (total time: 4 seconds)

范例2:线程池多任务先完成先返回处理结果(等价于范例1的效果,但是代码太复杂啦)

package com.contoso;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 
 * future.get()
 * future.get(long timeout, TimeUnit)
 */
public class ExecutorServiceExample2 {

    public static void main(String[] args) {
        int taskCount = 10;
        ExecutorService executor = Executors.newFixedThreadPool(taskCount);
        List> listFuture = new ArrayList();
        for (int i = 1; i <= taskCount; i++) {
            Future future = executor.submit(new MyTask(5000, i));
            listFuture.add(future);
        }

        while (taskCount > 0) {
            for (Future future : listFuture) {
                String data = null;
                try {
                    data = future.get(0, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    // 必须忽略超时异常,只要任务没有完成且等待时间为0就会报超时异常  
                    // e.printStackTrace();
                }

                if (data != null) {
                    System.out.println("主线程打印返回任务的处理时间:" + data); 
                    listFuture.remove(future);
                    taskCount--;                 
                    break;
                }
            }
        }

        executor.shutdown();
        System.out.println("所有任务已经完成,关闭线程池");
    }
}

class MyTask implements Callable {

    private int sleep;
    private int indexTask;
    Random random = new Random();

    public MyTask(int sleep, int indexTask) {
        this.sleep = sleep;
        this.indexTask = indexTask;
    }

    @Override
    public String call() throws Exception {
        long start = System.nanoTime();
        Thread.sleep(random.nextInt(sleep));// 模拟任务的执行时间    
        String data = Thread.currentThread().getName() + " Task" + indexTask + " Taken in seconds:";
        long end = System.nanoTime();
        double timeTaken = (end - start) / 1e9;
        System.out.println(Thread.currentThread().getName() + "|任务已处理完成");
        return timeTaken + " " + data;
    }
}
run:
pool-1-thread-1|任务已处理完成
主线程打印返回任务的处理时间:0.009673773 pool-1-thread-1 Task1 Taken in seconds:
pool-1-thread-8|任务已处理完成
主线程打印返回任务的处理时间:1.051098125 pool-1-thread-8 Task8 Taken in seconds:
pool-1-thread-6|任务已处理完成
主线程打印返回任务的处理时间:1.24212383 pool-1-thread-6 Task6 Taken in seconds:
pool-1-thread-2|任务已处理完成
主线程打印返回任务的处理时间:1.404322572 pool-1-thread-2 Task2 Taken in seconds:
pool-1-thread-7|任务已处理完成
主线程打印返回任务的处理时间:1.432703838 pool-1-thread-7 Task7 Taken in seconds:
pool-1-thread-4|任务已处理完成
主线程打印返回任务的处理时间:1.986656899 pool-1-thread-4 Task4 Taken in seconds:
pool-1-thread-10|任务已处理完成
主线程打印返回任务的处理时间:2.530709176 pool-1-thread-10 Task10 Taken in seconds:
pool-1-thread-3|任务已处理完成
主线程打印返回任务的处理时间:2.846413616 pool-1-thread-3 Task3 Taken in seconds:
pool-1-thread-9|任务已处理完成
主线程打印返回任务的处理时间:4.403490409 pool-1-thread-9 Task9 Taken in seconds:
pool-1-thread-5|任务已处理完成
主线程打印返回任务的处理时间:4.542559891 pool-1-thread-5 Task5 Taken in seconds:
所有任务已经完成,关闭线程池
BUILD SUCCESSFUL (total time: 4 seconds)

 

你可能感兴趣的:(Java多线程)