1. 并发基础
并发是指多个线程同时执行任务的能力。Java通过内置的多线程支持提供了强大的并发编程能力。
1.1 线程与进程
- 进程:操作系统中运行的程序,拥有独立的内存空间。
- 线程:进程中的执行单元,共享进程的内存,但有自己的栈。Java线程是轻量级的,适合并发任务。
- Java中,线程由
Thread
类或Runnable
接口实现。
1.2 创建线程
Java中有以下几种创建线程的方式:
-
继承
Thread
类:
class MyThread extends Thread {
public void run() {
System.out.println("MyThread running");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程
}
}
-
实现
Runnable
接口(推荐):
class MyRunnable implements Runnable {
public void run() {
System.out.println("MyRunnable running");
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
-
使用
ExecutorService
(现代方式,见后续线程池部分)。
1.3 线程状态
Java线程有以下状态:
- New:线程创建但未启动。
- Runnable:线程正在运行或等待CPU调度。
-
Blocked:线程等待锁(例如
synchronized
块)。 -
Waiting:线程等待其他线程的信号(如
wait()
、join()
)。 -
Timed Waiting:线程在有限时间内等待(如
sleep()
、wait(timeout)
)。 - Terminated:线程执行完成或异常终止。
2. 线程安全与同步
多个线程访问共享资源时,可能导致数据不一致或竞争条件。Java提供了多种机制来确保线程安全。
2.1 synchronized
关键字
synchronized
用于保护共享资源,防止多个线程同时访问。
- 同步方法:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
- 同步块(更灵活):
class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
}
2.2 volatile
关键字
volatile
确保变量的可见性(线程间的内存一致性),但不保证原子性。
class SharedData {
private volatile boolean flag = false;
public void setFlag() {
flag = true;
}
public boolean isFlag() {
return flag;
}
}
- 适用场景:适合简单状态标志,不适合复杂操作。
2.3 原子类
java.util.concurrent.atomic
包提供原子操作类(如AtomicInteger
),无需显式同步。
import java.util.concurrent.atomic.AtomicInteger;
class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
3. 锁机制(java.util.concurrent.locks)
java.util.concurrent.locks
包提供了更灵活的锁机制,优于synchronized
。
3.1 ReentrantLock
ReentrantLock
支持可重入锁,提供更细粒度的控制。
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 确保释放锁
}
}
}
-
特性:
- 支持公平锁(
new ReentrantLock(true)
)。 - 提供
tryLock()
等高级功能。
- 支持公平锁(
3.2 ReadWriteLock
适合读多写少的场景,允许多个线程同时读取,但写操作独占。
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class SharedData {
private int data = 0;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
lock.readLock().lock();
try {
System.out.println("Read: " + data);
} finally {
lock.readLock().unlock();
}
}
public void write(int value) {
lock.writeLock().lock();
try {
data = value;
} finally {
lock.writeLock().unlock();
}
}
}
4. 线程池与Executor框架
手动创建线程开销大,Java提供了ExecutorService
来管理线程池。
4.1 创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
executor.submit(() -> System.out.println("Task executed by " + Thread.currentThread().getName()));
}
executor.shutdown(); // 关闭线程池
}
}
-
常见线程池:
-
Executors.newFixedThreadPool(n)
:固定大小线程池。 -
Executors.newCachedThreadPool()
:动态大小线程池。 -
Executors.newSingleThreadExecutor()
:单线程执行。
-
4.2 Future
与异步任务
Future
用于获取异步任务的结果。
import java.util.concurrent.*;
public class FutureExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(() -> {
Thread.sleep(1000);
return 42;
});
System.out.println("Result: " + future.get()); // 阻塞等待结果
executor.shutdown();
}
}
5. 并发工具类
java.util.concurrent
包提供了多种高级并发工具。
5.1 Semaphore
(信号量)
控制同时访问资源的线程数量。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
private static final Semaphore semaphore = new Semaphore(2); // 允许2个线程并发
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
});
}
executor.shutdown();
}
}
-
注意:Java的
Semaphore
通常使用阻塞等待(让权等待),而不是忙等待,因为它依赖内核调度。
5.2 CountDownLatch
允许线程等待一组操作完成。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executor.submit(() -> {
System.out.println("Task completed");
latch.countDown();
});
}
latch.await(); // 等待3个任务完成
System.out.println("All tasks done");
executor.shutdown();
}
}
5.3 CyclicBarrier
让一组线程在某个点同步等待。
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached barrier"));
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " reached");
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
6. 并发集合
java.util.concurrent
提供了线程安全的集合类:
- ConcurrentHashMap:线程安全的哈希表,允许多线程并发读写。
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key", 1);
System.out.println(map.get("key"));
}
}
- CopyOnWriteArrayList:适合读多写少的场景,写操作会复制整个列表。
- BlockingQueue:线程安全的队列,用于生产者-消费者模式。
java
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Bloc
Top comments (0)