并发编程计数器怎么用的

时间:2025-03-04 18:34:51 明星趣事

在并发编程中,计数器是一种用于记录某个事件发生次数的数据结构。由于多个线程可能同时对计数器进行修改,因此需要保证计数器的线程安全性。以下是几种常用的计数器实现方式及其使用方法:

AtomicLong

介绍:AtomicLong是Java中的一个原子类,用于对长整形进行原子操作,保证并发情况下数据的安全性。它实现了一系列线程安全的方法,包括初始化为特定值和以原子方式设置当前值等。

使用

```java

import java.util.concurrent.atomic.AtomicLong;

public class Counter {

private AtomicLong count = new AtomicLong(0);

public void increment() {

count.incrementAndGet();

}

public long getCount() {

return count.get();

}

}

```

解释:AtomicLong通过CAS(Compare and Swap)操作来确保并发安全性。CAS是一种无锁算法,其核心思想是:如果内存中的值V符合预期值A,则将内存中值修改为B,否则不进行任何操作。整个过程是原子的,不会出现线程安全问题。

LongAdder

介绍:LongAdder是Java 8引入的一个类,用于在高并发环境下对长整形进行计数。它通过将计数分散到多个单元中来减少线程间的竞争,从而提高性能。

使用

```java

import java.util.concurrent.atomic.LongAdder;

public class Counter {

private LongAdder count = new LongAdder();

public void increment() {

count.increment();

}

public long getCount() {

return count.sum();

}

}

```

解释:LongAdder在内部维护了一组独立的单元,每个单元都可以独立地增加计数。当需要获取总和时,只需调用`sum()`方法。这种方法在多线程环境下比AtomicLong更高效,因为它减少了线程间的竞争。

LongAccumulator

介绍:LongAccumulator是Java 8引入的另一个类,用于对长整形进行原子累加操作。它支持自定义的累加函数,提供了比AtomicLong更灵活的计数方式。

使用

```java

import java.util.concurrent.atomic.LongAccumulator;

public class Counter {

private LongAccumulator count = new LongAccumulator((x, y) -> x + y, 0);

public void increment() {

count.accumulate(1);

}

public long getCount() {

return count.get();

}

}

```

解释:LongAccumulator接受一个二元操作符,用于定义如何将新值与当前值相加。这种方法允许在累加过程中执行更复杂的操作,而不仅仅是简单的加法。

CountDownLatch

介绍:CountDownLatch是Java中的一个同步工具,用于实现线程等待和唤醒。它允许一个或多个线程等待其他线程完成操作。

使用

```java

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class TeamBuildingDemo {

public static void main(String[] args) throws InterruptedException {

int memberCount = 5;

CountDownLatch readySignal = new CountDownLatch(memberCount);

CountDownLatch startSignal = new CountDownLatch(1);

ExecutorService executor = Executors.newFixedThreadPool(memberCount);

for (int i = 0; i < memberCount; i++) {

final String memberName = "队员" + (i + 1);

executor.submit(() -> {

try {

startSignal.await(); // 等待开始信号

System.out.println(memberName + "准备好了");

readySignal.countDown(); // 标记自己已准备好

// 执行其他任务

} catch (InterruptedException e) {

e.printStackTrace();

}

});

}

startSignal.countDown(); // 发出开始信号

executor.shutdown();

}

}

```

解释:CountDownLatch通过一个计数器来实现,计数器的初始值为线程数。每个线程在完成任务前调用`countDown()`方法,将计数器减一。