本文目录导读:

- 最基本的非线程安全计数器
- 使用synchronized的线程安全计数器
- 使用ReentrantLock的计数器
- 使用AtomicInteger的计数器(推荐)
- 完整的测试案例
- 批量操作的计数器
- 性能测试对比
- 最佳实践建议
我来为你详细介绍Java并发计数器的开发案例,从简单到复杂逐步实现。
最基本的非线程安全计数器
public class UnsafeCounter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
问题:多个线程同时调用increment()时,count++不是原子操作,会导致数据不一致。
使用synchronized的线程安全计数器
public class SynchronizedCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
使用ReentrantLock的计数器
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockCounter {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
使用AtomicInteger的计数器(推荐)
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // 原子自增
}
public int getCount() {
return count.get();
}
}
完整的测试案例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class CounterDemo {
// 1. 高性能计数器 - 使用AtomicInteger
static class HighPerformanceCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
// 2. 支持重置的计数器
static class ResettableCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
public void reset() {
count.set(0);
}
}
// 3. 有界计数器(不能超过最大值)
static class BoundedCounter {
private final AtomicInteger count = new AtomicInteger(0);
private final int max;
public BoundedCounter(int max) {
this.max = max;
}
public boolean increment() {
while (true) {
int current = count.get();
if (current >= max) {
return false; // 已达到最大值
}
if (count.compareAndSet(current, current + 1)) {
return true;
}
}
}
public int getCount() {
return count.get();
}
}
// 测试方法
public static void main(String[] args) throws InterruptedException {
testAtomicCounter();
testBoundedCounter();
}
private static void testAtomicCounter() throws InterruptedException {
System.out.println("=== 测试AtomicInteger计数器 ===");
HighPerformanceCounter counter = new HighPerformanceCounter();
int threadCount = 100;
int incrementsPerThread = 1000;
ExecutorService executor = Executors.newFixedThreadPool(10);
// 创建100个线程,每个线程自增1000次
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
for (int j = 0; j < incrementsPerThread; j++) {
counter.increment();
}
});
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
int expected = threadCount * incrementsPerThread;
int actual = counter.getCount();
System.out.println("期望值: " + expected);
System.out.println("实际值: " + actual);
System.out.println("结果正确: " + (expected == actual));
}
private static void testBoundedCounter() throws InterruptedException {
System.out.println("\n=== 测试有界计数器 ===");
BoundedCounter counter = new BoundedCounter(50);
ExecutorService executor = Executors.newFixedThreadPool(5);
// 多个线程尝试增加计数
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
for (int j = 0; j < 20; j++) {
boolean success = counter.increment();
if (success) {
System.out.println(Thread.currentThread().getName() + " 增加成功,当前值: " + counter.getCount());
}
}
});
}
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
System.out.println("最终计数值: " + counter.getCount() + " (不应超过50)");
}
}
批量操作的计数器
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntUnaryOperator;
public class BatchOperationCounter {
private final AtomicInteger count = new AtomicInteger(0);
// 批量增加
public int addAndGet(int delta) {
return count.addAndGet(delta);
}
// 条件更新
public int updateIf(IntUnaryOperator updateFunction) {
return count.updateAndGet(updateFunction);
}
// 仅在满足条件时更新
public boolean incrementIf(boolean condition) {
while (true) {
int current = count.get();
if (!condition) {
return false;
}
if (count.compareAndSet(current, current + 1)) {
return true;
}
}
}
public int getCount() {
return count.get();
}
}
性能测试对比
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class CounterPerformanceTest {
public static void main(String[] args) throws InterruptedException {
int threadCount = 10;
int iterations = 1000000;
// 测试synchronized
long syncTime = testSyncCounter(threadCount, iterations);
System.out.println("synchronized耗时: " + syncTime + "ms");
// 测试AtomicInteger
long atomicTime = testAtomicCounter(threadCount, iterations);
System.out.println("AtomicInteger耗时: " + atomicTime + "ms");
}
private static long testSyncCounter(int threadCount, int iterations) throws InterruptedException {
SynchronizedCounter counter = new SynchronizedCounter();
CountDownLatch latch = new CountDownLatch(threadCount);
long start = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
for (int j = 0; j < iterations; j++) {
counter.increment();
}
latch.countDown();
}).start();
}
latch.await();
return System.currentTimeMillis() - start;
}
private static long testAtomicCounter(int threadCount, int iterations) throws InterruptedException {
AtomicInteger counter = new AtomicInteger(0);
CountDownLatch latch = new CountDownLatch(threadCount);
long start = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
for (int j = 0; j < iterations; j++) {
counter.incrementAndGet();
}
latch.countDown();
}).start();
}
latch.await();
return System.currentTimeMillis() - start;
}
}
最佳实践建议
- 优先使用AtomicInteger:性能最好,实现简单
- 考虑使用LongAdder:高并发统计场景,性能更优
- 注意CAS的ABA问题:AtomicStampedReference可以解决
- 合理选择锁粒度:根据实际需求选择悲观锁或乐观锁
// 高并发统计场景使用LongAdder
import java.util.concurrent.atomic.LongAdder;
public class LongAdderCounter {
private final LongAdder count = new LongAdder();
public void increment() {
count.increment();
}
public long getCount() {
return count.sum(); // 注意:sum后会重置,需要重新累加
}
}
这些示例涵盖了常见的并发计数器实现方案,你可以根据具体需求选择最适合的实现方式。