Java多线程面试题:同步与异步的区别解析

Respondido utilizando GPT-4o-mini por Java Q&A Hub

Pregunta:

Java面试题之多线程 举例说明同步和异步。

Respuesta:

在Java中,多线程编程是一个重要的主题,理解同步和异步的概念对于编写高效的并发程序至关重要。下面我将通过示例来说明同步和异步的区别。

同步(Synchronous)

同步是指在多线程环境中,多个线程在访问共享资源时,必须按照一定的顺序进行,确保在同一时刻只有一个线程可以访问该资源。Java中可以使用synchronized关键字来实现同步。

示例:同步

class Counter {
    private int count = 0;

    // 使用synchronized关键字来保证线程安全
    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        
        // 创建多个线程来增加计数器
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("Final count: " + counter.getCount()); // 输出应为2000
    }
}

在这个例子中,increment方法是同步的,确保在同一时刻只有一个线程可以执行该方法,从而避免了数据竞争和不一致的问题。

异步(Asynchronous)

异步是指多个线程可以并行执行,而不需要等待其他线程完成。Java中可以使用CompletableFuture或其他异步编程模型来实现异步操作。

示例:异步

import java.util.concurrent.CompletableFuture;

public class AsynchronousExample {
    public static void main(String[] args) {
        // 创建一个异步任务
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000); // 模拟耗时操作
                System.out.println("Task 1 completed");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(500); // 模拟耗时操作
                System.out.println("Task 2 completed");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 等待所有异步任务完成
        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2);
        combinedFuture.join(); // 阻塞直到所有任务完成

        System.out.println("All tasks completed");
    }
}

在这个例子中,runAsync方法创建了两个异步任务,它们可以并行执行。主线程不会等待第一个任务完成后再开始第二个任务,而是同时启动两个任务。最后,使用allOf方法来等待所有异步任务完成。

总结

  • 同步:确保在同一时刻只有一个线程可以访问共享资源,避免数据竞争。使用synchronized关键字实现。
  • 异步:多个线程可以并行执行,主线程不需要等待其他线程完成。可以使用CompletableFuture等工具实现。

理解这两者的区别可以帮助你在多线程编程中做出更好的设计决策。