第五部分:Java 中的并发工具
Java 提供了多种并发工具类,帮助开发者更好地管理和控制多线程的执行。这些工具类主要位于 java.util.concurrent
包中(可点击跳转拓展一),提供了比传统的 synchronized
更强大和灵活的并发控制机制。
一、Lock 接口
Lock
接口是 Java 提供的一种比 synchronized
更灵活的锁机制。通过 Lock
,我们可以手动控制锁的获取和释放,支持尝试获取锁、定时获取锁等操作。
步骤
- 创建一个实现
Lock
接口的锁对象(如ReentrantLock
)。 - 在需要同步的代码块中,调用
lock()
方法获取锁,执行完后调用unlock()
方法释放锁。
示例代码
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class Counter {private int count = 0;private final Lock lock = new ReentrantLock(); // 创建 ReentrantLock 对象public void increment() {lock.lock(); // 获取锁try {count++;} finally {lock.unlock(); // 确保释放锁}}public int getCount() {return count;}
}public class LockExample {public static void main(String[] args) {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();try {t1.join();t2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("最终计数: " + counter.getCount()); // 应该是2000}
}
二、ReadWriteLock 接口
ReadWriteLock
允许多个读线程同时访问,但在写线程执行时,所有读线程和其他写线程都不能访问。这样可以提高读操作的性能。
步骤
- 创建一个
ReadWriteLock
对象(如ReentrantReadWriteLock
)。 - 使用
readLock()
和writeLock()
方法获取读锁和写锁。
示例代码
import java.util.concurrent.locks.ReentrantReadWriteLock;class ReadWriteCounter {private int count = 0;private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();public void increment() {rwLock.writeLock().lock(); // 获取写锁try {count++;} finally {rwLock.writeLock().unlock(); // 释放写锁}}public int getCount() {rwLock.readLock().lock(); // 获取读锁try {return count;} finally {rwLock.readLock().unlock(); // 释放读锁}}
}public class ReadWriteLockExample {public static void main(String[] args) {ReadWriteCounter counter = new ReadWriteCounter();Thread writer = new Thread(() -> {for (int i = 0; i < 1000; i++) counter.increment();});Thread reader = new Thread(() -> {for (int i = 0; i < 1000; i++) System.out.println("计数: " + counter.getCount());});writer.start();reader.start();try {writer.join();reader.join();} catch (InterruptedException e) {e.printStackTrace();}}
}
三、Semaphore
Semaphore
是一个计数信号量,允许一定数量的线程同时访问共享资源。可以用来控制对特定资源的访问量。
示例代码
import java.util.concurrent.Semaphore;class LimitedResource {private final Semaphore semaphore = new Semaphore(2); // 允许2个线程同时访问public void accessResource() {try {semaphore.acquire(); // 获取信号量System.out.println(Thread.currentThread().getName() + " 正在访问资源。");Thread.sleep(1000); // 模拟资源访问} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release(); // 释放信号量System.out.println(Thread.currentThread().getName() + " 已释放资源。");}}
}public class SemaphoreExample {public static void main(String[] args) {LimitedResource resource = new LimitedResource();for (int i = 0; i < 5; i++) {new Thread(resource::accessResource).start();}}
}
四、CountDownLatch
CountDownLatch
是一个同步辅助类,允许一个或多个线程等待其他线程完成一组操作。它的计数器可以设置为一个整数,调用 countDown()
方法可以将计数器减一,当计数器为零时,所有等待线程会被唤醒。
示例代码
import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(3); // 计数器设置为3Runnable task = () -> {try {Thread.sleep(1000); // 模拟任务System.out.println(Thread.currentThread().getName() + " 完成了.");} catch (InterruptedException e) {e.printStackTrace();} finally {latch.countDown(); // 减少计数器}};for (int i = 0; i < 3; i++) {new Thread(task).start();}latch.await(); // 等待计数器为零System.out.println("所有任务完成。");}
}
五、CyclicBarrier
CyclicBarrier
允许一组线程在某个点上相互等待,直到所有线程都达到该点。它可以重复使用,使得可以在多个循环中使用。
示例代码
import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample {public static void main(String[] args) throws InterruptedException {CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("所有线程到达了障碍。"));Runnable task = () -> {try {System.out.println(Thread.currentThread().getName() + " 正在执行工作...");Thread.sleep((long) (Math.random() * 1000));barrier.await(); // 等待其他线程到达} catch (Exception e) {e.printStackTrace();}};for (int i = 0; i < 3; i++) {new Thread(task).start();}}
}
总结
Java 提供的并发工具类如 Lock
、Semaphore
、CountDownLatch
和 CyclicBarrier
提供了比传统 synchronized
更灵活和强大的线程管理机制。了解它们的使用场景和特性有助于编写更高效和更安全的多线程程序。
下一步,我们将学习 Java 中的线程池,包括线程池的概念、使用方式以及常见的线程池实现类。
点我跳转下一课^_^