并发容器

背景

某些业务中因为使用HashMap这些线程不安全的结合类,如果因为线程不安全的问题导致了得到的结果我们的预期不一致,那么我们可以使用这些集合类对应的同步容器或者并发容器(JUC)包下。

集合类型对应的并容器补充
MapConcurrentHashMap
MapConcurrentSkipListMap
ListCopyOnWriteArrayList
ListConcurrentLinkedQueue
SetCopyOnWriteArraySet
SetConcurrentSkipListSet

Map

demo1

package com.mark.example.concurrent;

import com.mark.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 *
 * author:Mark
 * date:2018/7/31  11:53
 *
 * HashMap:线程不安全
 * HashTable:线程安全,效率低,锁住整个表
 * ConcurrentHashMap:采用锁分段机制
 *
 */
@Slf4j
@ThreadSafe
public class ConcurrentHashMapTest {
    public static int clientTotal = 5000;//请求总数
    public static int threadTotal = 200;//同时并发执行的线程数
    public static Map<Integer,Integer> map = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();//线程池
        final Semaphore semaphore = new Semaphore(threadTotal);//信号量,控制同时并发的线程数
        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 (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();//关闭线程池
        log.info("size:{}",map.size());
    }

    private static void update(int i) {//模拟并发的访问方法
        map.put(i, i);
    }
}

运行结果:线程安全

12:00:18.467 [main] INFO com.mark.example.concurrent.ConcurrentHashMapTest - size:5000


package com.mark.example.concurrent;

import com.mark.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.*;

/**
 * author:Mark
 * date:2018/7/31  11:53
 */
@Slf4j
@ThreadSafe
public class ConcurrentSkipListMapTest {
    public static int clientTotal = 5000;//请求总数
    public static int threadTotal = 200;//同时并发执行的线程数
    public static Map<Integer,Integer> map = new ConcurrentSkipListMap<>();

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();//线程池
        final Semaphore semaphore = new Semaphore(threadTotal);//信号量,控制同时并发的线程数
        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 (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();//关闭线程池
        log.info("size:{}",map.size());
    }

    private static void update(int i) {//模拟并发的访问方法
        map.put(i, i);
    }
}

运行结果:线程安全

12:01:10.247 [main] INFO com.mark.example.concurrent.ConcurrentSkipListMapTest - size:500


List

CopyOnWriteArrayList
demo3

package com.mark.example.concurrent;

import com.mark.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * author:Mark
 * date:2018/7/31  11:56
 *
 * 写入并复制:适合并发的时候迭代操作
 * 如果添加操作多时,效率低因为需要拷贝
 */
@Slf4j
@ThreadSafe
public class CopyOnWriteArrayListTest {
    public static int clientTotal = 5000;//请求总数
    public static int threadTotal = 200;//同时并发执行的线程数
    public static List<Integer> list = new CopyOnWriteArrayList<>();

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();//线程池
        final Semaphore semaphore = new Semaphore(threadTotal);//信号量,控制同时并发的线程数
        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 (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();//关闭线程池
        log.info("size:{}",list.size());
    }

    private static void update(int i) {//模拟并发的访问方法
        list.add(i);
    }
}

运行结果:线程安全

2:03:10.771 [main] INFO com.mark.example.concurrent.CopyOnWriteArrayListTest - size:5000


Set

CopyOnWriteArraySet

package com.mark.example.concurrent;

import com.mark.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.Set;
import java.util.concurrent.*;

/**
 * author:Mark
 * date:2018/7/31  11:59
 */
@Slf4j
@ThreadSafe
public class CopyOnWriteArraySetTest {
    public static int clientTotal = 5000;//请求总数
    public static int threadTotal = 200;//同时并发执行的线程数
    public static Set<Integer> set = new CopyOnWriteArraySet<>();


    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();//线程池
        final Semaphore semaphore = new Semaphore(threadTotal);//信号量,控制同时并发的线程数
        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 (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();//关闭线程池
        log.info("size:{}",set.size());
    }

    private static void update(int i) {//模拟并发的访问方法
        set.add(i);
    }
}

12:04:12.005 [main] INFO com.mark.example.concurrent.CopyOnWriteArraySetTest - size:5000


ConcurrentSkipListSet

package com.mark.example.concurrent;

import com.mark.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

/**
 * author:Mark
 * date:2018/7/31  11:57
 */
@Slf4j
@ThreadSafe
public class ConcurrentSkipListSetTest {
    public static int clientTotal = 5000;//请求总数
    public static int threadTotal = 200;//同时并发执行的线程数
    public static Set<Integer> set = new ConcurrentSkipListSet<>();


    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();//线程池
        final Semaphore semaphore = new Semaphore(threadTotal);//信号量,控制同时并发的线程数
        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 (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();//关闭线程池
        log.info("size:{}",set.size());
    }

    private static void update(int i) {//模拟并发的访问方法
        set.add(i);
    }
}

运行结果:线程安全

12:04:57.362 [main] INFO com.mark.example.concurrent.ConcurrentSkipListSetTest - size:5000

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值