欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

非阻塞线程编程之美

程序员文章站 2022-03-08 22:35:58
...

背景

今天年后最后一天了,是不是很羡慕?不要羡慕,虽然是最后一天了,但是我依然在code的路上,只不过没有在写业务代码了,而是在写一些自己感兴趣的东西,前几天翻了翻多线程的东西,感觉还是又有新的收获的,于是今天又抽空看了下。

线程阻塞

我们都知道多线程可以提高系统处理业务的能力,但是我们有没有考虑过,很多时候我们编写的多线程代码是阻塞的,尤其是主线程大部分需要阻塞,比如我们常用的join,还有future的get方法,当然很业务场景下,确实是需要阻塞的,比如上篇文章的最后一个demo
java多线程浅析之sleep、wait、join详解

但是!!!总有些场景主线程想要去干点别的事情的,今天就以泡茶案例来分析下非阻塞线程的编程之美。

案例分析:

  • 烧开水
  • 洗杯子
  • 泡茶、喝茶

烧水线程

public class HotWaterThread implements Callable<Boolean> {


    @Override
    public Boolean call()  {
        System.out.println("烧水中。。。。。。");
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

洗杯子线程

public class WashCupThread implements Callable<Boolean> {

    @Override
    public Boolean call(){
        System.out.println("洗杯子中。。。。。。");
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

测试线程泡茶喝水

@Test
    public void test2() throws ExecutionException, InterruptedException {
        FutureTask<Boolean> hotTask = new FutureTask<>(new HotWaterThread());
        Thread hotWater = new Thread(hotTask);
        FutureTask<Boolean> washTask = new FutureTask<>(new WashCupThread());
        Thread washCup = new Thread(washTask);
        ExecutorService pool = Executors.newFixedThreadPool(2);
        pool.submit(hotWater);
        pool.submit(washCup);
        Boolean h = hotTask.get();
        Boolean w = washTask.get();

        while (!(h && w)){
            System.out.println("看书咯。。。。。");
        }

        System.out.println("泡茶了。。。。。");
        System.out.println("喝茶了。。。。。");
    }

运行结果
非阻塞线程编程之美
很显然没有读书,问题出在哪呢?问题出在get方法那里,get方法是一个阻塞方法,直到线程结束,所以在执行烧水和洗杯子线程的时候,主线程是被阻塞的。

Guava异步回调

Guava是google公司提供的对java的扩展,Guava就实现了非阻塞异步回调获取future的功能,Guava的实现主要依赖以下两个接口:

  • ListenableFuture 继承了java的Future接口,使得异步结果能被监控
  • FutureCallback 新的接口,根据异步结果的不同,完成不同的回调处理

Guava实现泡茶并读书案例

public class GuavaTest {

    private static Boolean hW = false;
    private static Boolean wC = false;

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        // 创建烧水线程
        Callable<Boolean> hotWater = new HotWaterThread();
        // 创建洗杯子线程
        Callable<Boolean> washCup = new WashCupThread();
        // 构建java线程池
        ExecutorService jpool = Executors.newFixedThreadPool(2);
        // 构建guava线程
        ListeningExecutorService gpool = MoreExecutors.listeningDecorator(jpool);
        // 提交烧水线程
        ListenableFuture<Boolean> hotWaterFuture = gpool.submit(hotWater);
        // 烧水线程绑定异步回调
        Futures.addCallback(hotWaterFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean aBoolean) {
                hW = true;
                System.out.println("烧水成功");
            }

            @Override
            public void onFailure(Throwable throwable) {
                hW = false;
                System.out.println("烧水失败");
            }
        });

        // 提交洗杯子线程
        ListenableFuture<Boolean> washCupFuture = gpool.submit(washCup);
        Futures.addCallback(washCupFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean aBoolean) {
                wC = true;
                System.out.println("洗杯子成功");
            }

            @Override
            public void onFailure(Throwable throwable) {
                wC = false;
                System.out.println("洗杯子失败");
            }
        });

        while (!(hW && wC)){
            System.out.println("看书咯。。。。。。");
        }

        System.out.println("泡茶了。。。。。");
        System.out.println("喝茶了。。。。。");
        System.out.println(System.currentTimeMillis()- start + "毫秒");
    }
}

运行结果:
非阻塞线程编程之美
读书成功,因为烧水和洗杯子实现了真正的异步,就好比请了个佣人负责烧水和洗杯子,虽然仍然需要花费时间,但是我的精力已经不用关注烧水时水是否烧干的问题了。

总结

本文主要演示了阻塞线程和非阻塞线程的案例。

扫码关注个人公众号

非阻塞线程编程之美

相关标签: 多线程 java