Java并发面试题解析

1. 什么是并发和并行?

在计算机领域,"并发"和"并行"是两个常常被提到的概念。简单来说,"并发"指的是多个任务交替执行的过程,而"并行"则是多个任务同时执行的过程。在Java中,我们通过多线程来实现并发和并行编程。

2. Java中的线程与进程

Java中的线程是程序执行的最小单位,一个进程可以包含多个线程。线程可以轻松地实现并发编程,通过多个线程同时执行程序,提高程序的性能和效率。

public class MyThread extends Thread {
    public void run() {
        System.out.println("This is a thread.");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

在上面的代码中,我们定义了一个继承自Thread的线程类MyThread,并重写了run()方法,在main方法中创建了一个线程对象并启动它。线程启动后会执行run()方法中的代码。

3. Java中的线程池

Java中的线程池是一种重要的并发编程机制,它可以复用线程、控制线程数量、管理线程执行等。使用线程池可以避免频繁创建和销毁线程,提高性能。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyThreadPool {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.execute(worker);
        }

        executor.shutdown();
        while (!executor.isTerminated()) {
        }

        System.out.println("All threads finished.");
    }
}

class WorkerThread implements Runnable {
    private String message;

    public WorkerThread(String message) {
        this.message = message;
    }

    public void run() {
        System.out.println(Thread.currentThread().getName() + " Start. Message = " + message);
        processMessage();
        System.out.println(Thread.currentThread().getName() + " End.");
    }

    private void processMessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上面的代码中,我们通过ExecutorService创建了一个固定大小为5的线程池,然后创建了10个WorkerThread对象,并将它们提交给线程池执行。最后调用shutdown()方法关闭线程池。

4. Java中的同步和锁

在多线程环境下,为了避免多个线程同时访问共享资源导致数据异常,我们需要使用同步机制来保证线程安全。Java提供了synchronized关键字和Lock接口来实现同步。

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample example = new SynchronizedExample();

        ExecutorService executor = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 1000; i++) {
            executor.submit(() -> example.increment());
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);

        System.out.println("Final count: " + example.count);
    }
}

在上面的代码中,我们定义了一个SynchronizedExample类,其中包含一个count变量和一个increment()方法,使用synchronized关键字修饰。在main方法中创建了一个线程池,提交1000个任务给线程池执行,最后输出count的值。

5. Java中的原子操作和CAS

Java中的原子操作是指在多线程环境下可以保证操作的完整性,不会被打断。Java提供了Atomic包下的类来支持原子操作,其中最常用的是AtomicInteger、AtomicLong等。CAS(Compare And Swap)是一种乐观锁机制,可以实现原子操作。

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.getAndIncrement();
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicExample example = new AtomicExample();

        ExecutorService executor = Executors