1. 如何实现并发编程
定义
并发编程是指在同一时间段内,让多个任务可以同时执行的编程方式。在 Java 里,主要借助多线程机制达成并发编程,通过创建多个线程,让它们在同一进程中并行执行不同任务。线程作为 CPU 调度的最小单元,Java 提供了丰富的 API 用于创建、管理和控制线程。
要点
- 线程创建:有继承
Thread
类、实现Runnable
接口、实现Callable
接口并结合FutureTask
这三种方式。 - 线程同步:使用
synchronized
关键字、Lock
接口及其实现类,保证线程安全,防止多个线程同时访问共享资源引发数据不一致问题。 - 线程通信:利用
wait()
、notify()
和notifyAll()
方法,或者Condition
接口实现线程间协作。 - 线程池使用:借助
ExecutorService
管理线程生命周期,提升线程复用性与性能。
代码示例
import java.util.concurrent.*;
// 继承 Thread 类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
// 实现 Runnable 接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}
// 实现 Callable 接口
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable result: " + Thread.currentThread().getName();
}
}
public class ConcurrencyExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 继承 Thread 类创建线程
MyThread thread = new MyThread();
thread.start();
// 实现 Runnable 接口创建线程
MyRunnable runnable = new MyRunnable();
Thread runnableThread = new Thread(runnable);
runnableThread.start();
// 实现 Callable 接口创建线程
MyCallable callable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread callableThread = new Thread(futureTask);
callableThread.start();
System.out.println(futureTask.get());
// 使用线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(runnable);
Future<String> future = executorService.submit(callable);
System.out.println(future.get());
executorService.shutdown();
}
}
应用
- Web 服务器:处理大量并发的客户端请求,提高服务器响应能力。
- 大数据处理:并行处理大规模数据,提升数据处理效率。
2. Java 锁有哪些种类,有什么区别
定义
Java 中的锁是用于控制多个线程对共享资源的访问,保障线程安全的机制。
种类及区别
synchronized
锁- 定义:基于对象头的 Mark Word 实现,属于 JVM 层面的锁。
- 特点:自动获取和释放锁,为非公平锁,支持可重入,适用于简单的同步场景。
ReentrantLock
锁- 定义:基于 AQS(AbstractQueuedSynchronizer)实现,是 Java 语言层面的锁。
- 特点:需手动获取和释放锁,可实现公平锁和非公平锁,支持可重入,功能更灵活,适用于复杂的同步场景。
ReentrantReadWriteLock
锁- 定义:基于 AQS 实现,将锁分为读锁和写锁。
- 特点:读锁可被多个线程同时持有,写锁为独占锁,适用于读多写少的场景。
StampedLock
锁- 定义:JDK 8 引入的新锁,基于乐观读的思想。
- 特点:提供乐观读、悲观读和写锁三种模式,性能更高,适用于读多写少且对性能要求较高的场景。
代码示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
// 使用 synchronized 锁
class SynchronizedLockExample {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
// 使用 ReentrantLock 锁
class ReentrantLockExample {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
// 使用 ReentrantReadWriteLock 锁
class ReentrantReadWriteLockExample {
private int count = 0;
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
public void increment() {
writeLock.lock();
try {
count++;
} finally {
writeLock.unlock();
}
}
public int getCount() {
readLock.lock();
try {
return count;
} finally {
readLock.unlock();
}