【好记性不如烂笔头】IO之深入理解同步、异步、阻塞、非阻塞


一、什么是同步?

先简单画一个图再解释:
同步
我打算做番茄炒蛋,于是我去街上买点西红柿买点鸡蛋然后拿回家做。
假设我的步骤如下:

  1. 买西红柿
  2. 买鸡蛋
  3. 炒鸡蛋
  4. 炒西红柿

这就是我的操作顺序,所以–>
同步: 在同一个时间点我只能干一样事情,我只能一件干完再去干下一件事。

public class 同步 {

	public static void main(String[] args) {
		int i = 1;
		i = 买西红柿(i);
		i = 买鸡蛋(i);
		i = 炒鸡蛋(i);
		i = 炒西红柿(i);
		System.out.println("做好啦!");
	}

	private static int 买西红柿(int i) {
		System.out.println("第" + (i++) + "步:我去买西红柿了");
		return i;
	}

	private static int 买鸡蛋(int i) {
		System.out.println("第" + (i++) + "步:我去买鸡蛋了");
		return i;
	}

	private static int 炒鸡蛋(int i) {
		System.out.println("第" + (i++) + "步:我去炒鸡蛋了");
		return i;
	}

	private static int 炒西红柿(int i) {
		System.out.println("第" + (i++) + "步:我去炒西红柿了");
		return i;
	}
}

代码示例


二、什么是异步?

还是先画图再解释
异步
小李:我去买西红柿炒西红柿,小张你呢去买点鸡蛋炒一下再给我,然后我再西红柿鸡蛋一起炒。

小张买鸡蛋和小李买西红柿有关系吗?没有关系,他俩是异步的
小张买鸡蛋和小张炒鸡蛋有关系吗?有关系,他俩是同步的
小张炒鸡蛋和小李番茄炒蛋有关系吗?有关系,小李要得到鸡蛋才能番茄炒蛋,他俩是同步的

小张可以做自己的事情,同时小李也可以做自己的事情,这就是异步。

测试代码:


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class 异步 {

	public static void main(String[] args) throws ExecutionException, InterruptedException {
		for(int i = 0;i<10;i++) {
			做饭();
			System.out.println("=================");
		}
	}
	
	public static void 做饭() throws InterruptedException, ExecutionException {
		CompletableFuture<Boolean> 小张你要做的事情 = CompletableFuture.supplyAsync(() -> {
			try {
				买鸡蛋();
				return 炒鸡蛋();
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			return false;
		});
		买西红柿();
		炒西红柿();
		if (小张你要做的事情.get()) {
			番茄炒蛋();
		}
	}
	
	private static void 买西红柿() throws InterruptedException {
		System.out.println(System.currentTimeMillis() + ":我去买西红柿了");
		Thread.sleep(1000);
	}

	private static void 买鸡蛋() throws InterruptedException {
		System.out.println(System.currentTimeMillis() + ":我去买鸡蛋了");
		Thread.sleep(1000);
	}

	private static boolean 炒鸡蛋() throws InterruptedException {
		System.out.println(System.currentTimeMillis() + ":我去炒鸡蛋了");
		Thread.sleep(1000);
		return true;
	}

	private static void 炒西红柿() throws InterruptedException {
		System.out.println(System.currentTimeMillis() + ":我去炒西红柿了");
		Thread.sleep(1000);
	}
	
	private static void 番茄炒蛋() throws InterruptedException {
		System.out.println(System.currentTimeMillis() + ":番茄鸡蛋一起炒");
		Thread.sleep(1000);
	}
}

异步代码示例
买西红柿一定在炒西红柿前面,有先后顺序,同步
买鸡蛋一定在炒鸡蛋前面,有先后顺序,同步
买西红柿不一定在买鸡蛋前面,无先后顺序,不需要等待另一个完成,异步
炒西红柿不一定在炒鸡蛋前面,无先后顺序,不需要等待另一个完成,异步
上述四个一定在番茄炒蛋前面,有先后顺序,必须等待上面的完成,同步


什么是阻塞?

阻塞
有这样一条河流,本来挺顺畅的一泻千里,突然来了块大石头矗立在河流中央,水流无法正常通过了,这就是阻塞。
河道就比方我们的CPU,水流就是线程,出现大石头阻塞了,水流等待(线程挂起)
阻塞之后河道(CPU)还在,但水流(线程)没了,河道(CPU)是不是闲着。
同样,假设咱们有1000个线程,都要执行这个逻辑,你在这阻塞着,这1000个线程是不是很快都挂起了,这样任务没处理掉,cpu还闲着没事干。
所以我们有了非阻塞,不能让你CPU闲着,该干活还要给我干活
万恶的资本家


什么是非阻塞?

非阻塞

非阻塞就是,前方有大石头了,你也直接给我过掉,返回一个值,让我知道你失败了,我轮询下一个,这样CPU利用率就相对来说高一些了。

Java的发展历程其实就是不断的发现问题然后解决问题的过程,非阻塞性能就好了吗?其实也不然,非阻塞采用轮询的方式,就浪费了CPU时间片,性能依然不好。
那怎么才能同时检测多个,还不浪费CPU时间片呢,这个就有一个新的东西出来了,叫IO多路复用,这个下次再写。

总结

同步、异步 和 阻塞、非阻塞 个人感觉角度不一样。
同步:线程主动的等待结果
阻塞:线程被动的等待结果
异步:线程直接忙别的,不管了或者等待回调然后才继续
非阻塞:线程忙别的,时不时的过来瞅瞅好了没
纯属个人理解,如果有不对的地方,欢迎大家指正呀😀

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泪梦殇雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值