计算机系统应用教程网站

网站首页 > 技术文章 正文

深入理解同步、异步、阻塞、非阻塞

btikc 2024-10-21 04:09:59 技术文章 7 ℃ 0 评论

#头条创作挑战赛#

一、什么是同步?

先简单画一个图再解释:


我打算做番茄炒蛋,于是我去街上买点西红柿买点鸡蛋然后拿回家做。
假设我的步骤如下:

  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多路复用,这个下次再写。

总结

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

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表