【并发编程】-- Promise接口使用

64 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情

Promise接口使用

Future接口调用线程需要通过线程池或者由FutureTask类创建,而后需要主线程执行get方法以获取结果,然后再执行相应的动作,其实有一种方式能够在调用线程时无须通过Future.get()方法获取到结果,就能进一步执行的动作,而这些回调的动作由执行Future任务的线程在执行完Future后自动调用,那方式就是使用Promise接口。

实现代码如下:

public class PromiseRun {
    public static void main(String[] args) {
        DefaultEventExecutor defaultEventExecutor = new DefaultEventExecutor();
        Promise<String> promise = defaultEventExecutor.newPromise();
        promise.addListener((FutureListener<String>)future-> System.out.println(future.get()));
        defaultEventExecutor.submit(new Callable<String>(){
            @Override
            public String call() throws Exception {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                promise.setSuccess(String.valueOf(System.currentTimeMillis()));
                return "Gxin";
            }
        });
        defaultEventExecutor.shutdown();
        try {
            defaultEventExecutor.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

[main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework

1666335131350

注意点:

DefaultEventExecutor()方法是创建Netty默认执行器,由该执行器创建Promise对象,并且添加监听器,监视器将在任务完成时自动调用。promise.setSuccess(String)方法可以设置任务执行完成结果,此时会自动调用监听器。

因此,通过Promise接口,可以实现任务执行完成后自动回调,而不用调用线程通过Future接口调用get()方法获取结果后再处理结果,这才是真正的异步调用。

Volatile关键字使用

被volatile关键字修饰的变量,编译器和运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重新排序,在java并发编程中,该变量常用于防止指令重排序,在访问volatile变量时不会执行加锁操作,也就不会执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量的同步机制,但是这个机制仅仅只是保证了可见性而已。