一、核心区别
1. 同步(Synchronous)
1、定义:任务按顺序逐一执行,当前任务未完成时,后续任务必须等待。
2、特点:
-
阻塞性:当前任务会阻塞后续任务,直到完成。
-
简单直观:代码按顺序执行,易于理解和调试。
-
性能瓶颈:若任务耗时长,可能导致页面卡顿(前端)或线程阻塞(后端)。
2. 异步(Asynchronous)
1、定义:任务不按顺序执行,当前任务发起后,后续任务可立即执行,无需等待当前任务完成。
2、特点:
-
非阻塞性:当前任务不会阻塞后续任务,提升性能和响应速度。
-
回调机制:通过回调函数、Promise、CompletableFuture(Java)等处理异步结果。
-
复杂性:代码逻辑可能分散,调试难度增加。
二、前端中的同步与异步
1、同步场景
示例:输出顺序严格按代码顺序执行。
javascript
JavaScript
console.log('开始');
console.log('执行任务1');
console.log('执行任务2');
console.log('结束');
应用场景:简单的逻辑操作,如变量赋值、基础计算。
2、异步场景
示例 :输出顺序:开始 → 结束 → 异步任务(2秒后)。
javascript
JavaScript
console.log('开始');
setTimeout(() => {
console.log('异步任务');
}, 2000);
console.log('结束');
常见实现方式:
-
回调函数 :如
setTimeout、XMLHttpRequest。 -
Promise:
```JavaScript javascript new Promise((resolve, reject) => {
javascriptJavaScript setTimeout(() => resolve('完成'), 2000);}).then(result => console.log(result));
javascript
- **async/await**:
```JavaScript
JavaScript
async function fetchData() {
console.log('开始');
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('异步任务');
}
fetchData();
应用场景:
-
网络请求(如 AJAX、Fetch API)。
-
动画、用户交互事件。
-
定时任务(如
setTimeout、setInterval)。
三、Java 后端中的同步与异步
1. 同步场景
示例(阻塞式文件读取):
java
import java.io.*;
public class SyncExample {
public static void main(String[] args) {
System.out.println("开始");
try {
// 模拟同步文件读取(阻塞当前线程)
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("结束");
}
}
特点:
-
reader.readLine()是阻塞操作,文件未读取完时,后续代码无法执行。 -
简单直观,但可能影响性能。
应用场景:
-
简单的脚本任务。
-
无需高并发的场景。
2. 异步场景
示例 (使用 CompletableFuture 实现异步文件读取):
java
import java.io.*;
import java.nio.file.*;
import java.util.concurrent.*;
public class AsyncExample {
public static void main(String[] args) {
System.out.println("开始");
CompletableFuture.supplyAsync(() -> {
try {
// 模拟异步文件读取(非阻塞)
return new String(Files.readAllBytes(Paths.get("file.txt")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}).thenAccept(content -> {
System.out.println("文件内容:");
System.out.println(content);
}).exceptionally(e -> {
System.err.println("读取文件失败:" + e.getMessage());
return null;
});
System.out.println("结束(主线程未阻塞)");
// 防止主线程提前退出
try { Thread.sleep(3000); } catch (InterruptedException e) {}
}
}
特点:
-
CompletableFuture.supplyAsync()提交异步任务,主线程不会被阻塞。 -
使用
thenAccept()处理异步结果。
其他异步实现方式:
-
线程池:
```Java java ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
java// 异步任务 System.out.println("异步任务执行中...");});
executor.shutdown();
java
- **Spring 异步方法**(使用 `@Async` 注解):
```Java
java
@Service
public class AsyncService {
@Async
public void asyncMethod() {
System.out.println("异步任务执行中...");
}
}
应用场景:
-
高并发场景(如 Web 服务器、数据库操作)。
-
I/O 密集型任务(如文件读写、网络请求)。
四、总结与选择建议
1、前端:
-
同步:适用于简单逻辑,如变量赋值、基础计算。
-
异步:适用于网络请求、动画、用户交互等需要非阻塞的场景。
2、Java 后端:
-
同步:适用于简单脚本任务或无需高并发的场景。
-
异步:适用于高并发、I/O 密集型任务,如 Web 服务器、数据库操作。
3、选择原则:
-
性能优先:复杂任务优先选择异步,避免阻塞。
-
可维护性优先:简单任务优先选择同步,代码更直观。
-
平衡点:结合业务需求,合理使用同步与异步。