JUCHashMap 非安全容器bing

Posted 鸟随二月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUCHashMap 非安全容器bing相关的知识,希望对你有一定的参考价值。

上一篇

JUC(Java并发包)

java.util.concurrent包下的类
JUC包下的所有类都是线程安全的,JUC下有:

1.ReentrantLock(可重入锁)

2.Semaphore(信号量)

   // 创建信号量
        Semaphore semaphore = new Semaphore(2);

        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
                0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000));

        // 执行任务 1
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() +
                        " 到达停车场门口");
                try {
                    Thread.sleep(1000);
                    // 尝试获取锁
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行到此行代码表示已经获取到了停车位
                System.out.println(Thread.currentThread().getName() +
                        " 进入了停车场");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +
                        " 离开了停车场");
                // 释放锁
                semaphore.release();
            }
        });

        // 执行任务 2
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() +
                        " 到达停车场门口");
                try {
                    Thread.sleep(1000);
                    // 尝试获取锁
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行到此行代码表示已经获取到了停车位
                System.out.println(Thread.currentThread().getName() +
                        " 进入了停车场");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +
                        " 离开了停车场");
                // 释放锁
                semaphore.release();
            }
        });

        // 执行任务 2
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() +
                        " 到达停车场门口");
                try {
                    Thread.sleep(1000);
                    // 尝试获取锁
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行到此行代码表示已经获取到了停车位
                System.out.println(Thread.currentThread().getName() +
                        " 进入了停车场");
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +
                        " 离开了停车场");
                // 释放锁
                semaphore.release();
            }
        });

        // 执行任务 2
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() +
                        " 到达停车场门口");
                try {
                    Thread.sleep(1000);
                    // 尝试获取锁
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行到此行代码表示已经获取到了停车位
                System.out.println(Thread.currentThread().getName() +
                        " 进入了停车场");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +
                        " 离开了停车场");
                // 释放锁
                semaphore.release();
            }
        });

    }

3. CountDownLatch(计数器)

等待所有的线程进入某个步骤之后,再统一执行某个流程。

  public static void main(String[] args) throws InterruptedException {
        // 创建 CountDownLatch
        CountDownLatch countDownLatch =
                new CountDownLatch(3);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
                0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100));

        for (int i = 0; i < 6; i++) {
            // 执行任务
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() +
                            " 开跑");
                    int num = new Random().nextInt(5);
                    num += 1;
                    try {
                        Thread.sleep(num * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() +
                            " 到达了终点");
                    // 计数器 -1
                    countDownLatch.countDown();
                }
            });
        }
       

        // 等待所有的选手都到达终点,等待计时器为 0,在执行之后的结果
        countDownLatch.await();

        System.out.println("比赛结束,宣布成绩");

    }

CountDownLauth执行的原理:
就是内有有一个计数器,当执行了countDown计时器-1,直到减到О那么这个计时器就使用完毕了,就可以执行await之后的代码了。
CountDownLauth 缺点:计时器只能使用一次。

4. CyclicBarrier(循环屏障)

public static void main(String[] args) throws InterruptedException {
                CyclicBarrier cyclicBarrier =
                new CyclicBarrier(2, new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("-----------到达了屏障-----------");
                    }
                });

        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
                0, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000));

        for (int i = 1; i < 5; i++) {
            final int finalI = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(finalI * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() +
                            " 进入了任务");
                    try {
                        // 等待其他线程执行
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() +
                            " 执行结束");
                }
            });
        }

    }

CyclicBarrie执行原理:内有一个计数器,每次线程执行到 await 方法的时候,计时器+1,直到计时器个数等于创建时声明的格式的时候,就会突破屏障,执行之后的代码;在突破屏障之后计时器清零可以进行下一轮的执行了。

HashMap 非安全容器

多线程下的问题:

JDK 1.7 头插法->死循环

单线程时
在这里插入图片描述

在这里插入图片描述
多线程时
1.
在这里插入图片描述
2.e2执行完时
在这里插入图片描述
3.e1继续执行
在这里插入图片描述
JDK 1.8尾插法-〉数据覆盖
在这里插入图片描述

HashMap的安全版本:ConcurrentHashMap

ConcurrentHashMap 实现线程安全原理是在进修改操作的时候(put),会在进入方法之后加锁,并且在操作完成之后释放锁,所以不会有线程安全的问题。
ConcurrentHashMap 优化:是将HashMap 分成多个sengment对每个sengment分别进行加锁,这样就可以保证。多线程如果操作的不是同一个sengment就不需进行排队处理了,从而提高了程序的执行效果。
分段锁:锁粒度更小,性能更高。
HashMap是非线程安全的
HashTable ->线程安全的(在put上使用的时synchronized)整体给对象进行加锁

以上是关于JUCHashMap 非安全容器bing的主要内容,如果未能解决你的问题,请参考以下文章

多线程(上篇)bing

多线程(上篇)bing

云原生容器场景下的内核安全

CPNtools协议建模安全分析---实例变迁标记

Java多线程之~~~线程安全容器的非堵塞容器

Cordova + Bing 地图 + 内容安全策略