J.U.C
- 其實(shí)就是JDK提供的一個(gè)包:java.util.concurrent
CopyOnWriteArrayList
- 相較于ArrayList五鲫,CopyOnWriteArrayList是線程安全的湘今;
- 在添加新元素時(shí)塞淹,先將數(shù)組拷貝一份玲昧,在新數(shù)組中寫栖茉,寫完在把引用指向新數(shù)組;
- CopyOnWriteArrayList的add操作是在鎖的保護(hù)下進(jìn)行的孵延;
- 讀操作是在原數(shù)組上進(jìn)行的吕漂,不需要加鎖;
CopyOnWriteArrayList缺點(diǎn)
- 寫操作時(shí)復(fù)制數(shù)組尘应,消耗內(nèi)存惶凝;
- 不能用于實(shí)時(shí)讀的場(chǎng)景,在多線程情況下犬钢,可能讀到落后的數(shù)據(jù)苍鲜,寫期間允許讀;
- 在頻繁的寫操作時(shí)慎用娜饵,在高性能互聯(lián)網(wǎng)應(yīng)用中坡贺,很容易引起故障;
通常箱舞,共享的List不會(huì)很大遍坟,修改的情況也會(huì)很少,CopyOnWriteArrayList可以代替ArrayList滿足線程安全的要求晴股;
CopyOnWriteArrayList示例
import com.example.concurrency.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
@Slf4j
@ThreadSafe
public class CopyOnWriteArrayListExample {
// 請(qǐng)求總數(shù)
public static int clientTotal = 5000;
// 同時(shí)并發(fā)執(zhí)行的線程數(shù)
public static int threadTotal = 200;
private static List<Integer> list = new CopyOnWriteArrayList<>();
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() -> {
try {
semaphore.acquire();
update(count);
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("size:{}", list.size());
}
private static void update(int i) {
list.add(i);
}
}
輸出:
13:59:46.178 [main] INFO com.example.concurrency.example.concurrent.CopyOnWriteArrayListExample - size:5000