Java笔记2.6--线程并发深入

1.同步计数器CountDownLatch

2.线程通过Callable返回结果,通过Future获取结果

3.通过CompletableFuture管理多线程(基于jdk1.8)

CountDownLatch:

有一个正数计数器。

countDown()方法对计数器做减操作。直到所有的计数器归0(或中断或超时),await线程才会继续,否则一直阻塞。能保证以CountDownLatch所标记的前置任务都完成后,主任务再执行。

通过Callable类对象得到返回结果。用future得到Callable的返回。多个线程任务用线程池管理。调用3个任务里全部得到结果后,再把结果一并组装成list,用CountDownLatch统计3个线程的完成情况。通过await设置服务超时时间。

class Task implements Callable<String>{
    private CountDownLatch latch;
    private String taskName;

    public Task(CountDownLatch latch, String taskName){
        this.latch = latch;
        this.taskName = taskName;
    }

    public String call() throws Exception{
        try {
            //省略3个url里得到结果的步骤,结果模拟演示为为API Result
            return "APT Result " + taskName;
        }
        finally {
            latch.countDown();//减小计数
            System.out.println(taskName + " " + latch.getCount());
        }
    }
}
public class CountDownLatchDemo {
    public static void main(String[] args){
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<String> resultList = new ArrayList<>();
        CountDownLatch latch = new CountDownLatch(3);

        Future<String> future1 = executorService.submit(new Task(latch, "Task1"));
        Future<String> future2 = executorService.submit(new Task(latch, "Task2"));
        Future<String> future3 = executorService.submit(new Task(latch, "Task3"));

        try {
            latch.await(4000,TimeUnit.MILLISECONDS);
            System.out.println("Count Down All Finished");
            resultList.add(future1.get());
            resultList.add(future2.get());
            resultList.add(future3.get());
        }catch (Exception e){
            e.printStackTrace();
        }
        executorService.shutdown();
        Iterator<String> it = resultList.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}
输出:
Task2 1
Count Down All Finished
Task3 0
Task1 2
APT Result Task1
APT Result Task2
APT Result Task3
//Count一定在result前面

Future局限性和实际需求:

每个Future是独立的,多个Future很难关联

实际上要合并多个线程计算结果

多个线程并发,谁先返回就用谁的结果

扫描二维码关注公众号,回复: 11529869 查看本文章

CompletableFuture:

基于jdk1.8

1.在supplyAsnc方法中定义要执行的任务

2.通过thenAccept方法,消费之前线程的结果

public class CompletableFutrueDemo {
    /**
     * 第一个线程得到结果"result"可以在第二个线程中使用
     * @param args
     */
    public static void main(String[] args){
        CompletableFuture.supplyAsync(()->{return "result";}).
                thenAccept(v -> { System.out.println("Use the result: "+ v);});
    }
}
输出:
Use the result: result

3.通过thenCombine方法整合多个线程的返回结果

public class CompletableFutureCombine {
    public static void main(String[] args){
        String combineResult = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return "part1";
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return "part2";
        }),(result1,result2)->{return result1 + " " + result2;}).join();
        System.out.println(combineResult);
    }
}
输出:
part1 part2

4.通过applyToEither方法,使用先返回的结果

public class CompletableFutureUseFast {
    public static void main(String[] args){
        String result = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return "Running 1 second";
        }).applyToEither(CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(3000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return "Running 3 seconds";
        }),(s)->{return s;}).join();
        System.out.println(result);
    }
}
输出:
Running 1 second

说辞:可以找个业务点说到CountDownLatch

CompletableFuture一般未必使用,但是要了解

总结:

1.了解通过CountDownLatch管理多线程协作的方法

2.了解通过Callable返回线程结果的方法

3.掌握用CompletableFuture类管理多线程间依赖的做法

猜你喜欢

转载自blog.csdn.net/lfanchenyu/article/details/107613078