程序员社区

阻塞、非阻塞、同步、异步

这几个概念困扰了我好久,现在此做下总结:

阻塞:阻塞通常是指在一个执行过程中暂停,以等待某个条件的触发。(包括IO 阻塞、线程阻塞)

同步/异步:表示的发出调用后,被调用者是否立即返回。

阻塞/非阻塞:表示调用方线程是否在等待数据就绪(例如:Socket通道数据是否已读入内存)

以下图为例解释一下:其中读取数据分为2个步骤,1. 内核等待数据可读,2. 将内核读到的数据拷贝到进程,其中第一个步骤为阻塞的(因为他在等待数据就绪),而第二个步骤为非阻塞的。

阻塞、非阻塞、同步、异步插图
描述的是从网卡读取UDP数据包的过程

这张图在第一个步骤中,应用进程不断的询问内核,当数据没有就绪时,内核会立即返回,此时调用放线程也并未阻塞着等待数据就绪,可以做其他事情,所以第一个步骤为“异步非阻塞”的。

而第二个步骤,应用进程开始系统调用copy数据到用户空间,此时这个调用没有立即返回,再结合上面的分析,所以这个步骤为“同步非阻塞的”。

在Java中实现同步阻塞调用、异步阻塞调用、异步非阻塞调用:

同步阻塞调用:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        /* 同步阻塞调用: 
            调用没有立即返回 => 同步
            等待了数据就绪 => 阻塞
         */
        int result = func();
        func2(result);
    }
    
    public static int func() throws InterruptedException {
        // 模拟(IO)阻塞
        Thread.sleep(1000L);
        
        // 模拟计算操作
        return 1 + 1;
    }

    private static void func2(Integer result) {
        // do something...
    }
}
阻塞、非阻塞、同步、异步插图1

同步非阻塞演示不了

异步阻塞调用(此处使用join也能表现出来):

public class Test {

    public static void main(String[] args) throws Exception {
        /* 异步阻塞调用:
            调用后立即返回 => 异步
            返回后main线程直接获取结果,等待了数据就绪 => 阻塞
         */
        FutureTask<Integer> futureTask = new FutureTask<>(Test::func);
        new Thread(futureTask).run();

        Integer result = futureTask.get();
        func2(result);
    }

    private static int func() throws InterruptedException {
        // 模拟(IO)阻塞
        Thread.sleep(1000L);

        // 模拟计算操作
        return 1 + 1;
    }
    
    private static void func2(Integer result) {
        // do something...
    }

}
阻塞、非阻塞、同步、异步插图2

异步非阻塞调用:

public class Test {

    public static void main(String[] args) throws Exception {
        /* 异步非阻塞调用:
            调用后立即返回 => 异步
            调用后main线程直接就不管了,交由t1线程执行后续的操作,main线程也没有等待数据就绪 => 非阻塞
         */
        CompletableFuture.supplyAsync(() -> func())
                .thenAccept(result -> func2(result));
    }

    private static int func() {
        // 模拟(IO)阻塞
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 模拟计算操作
        return 1 + 1;
    }


    private static void func2(Integer result) {
        // do something...
    }

}
阻塞、非阻塞、同步、异步插图3

https://mp.weixin.qq.com/s/YzpC0BP3K5jEc7qlWtzBTw

赞(0) 打赏
未经允许不得转载:IDEA激活码 » 阻塞、非阻塞、同步、异步

一个分享Java & Python知识的社区