美文网首页
JUC学习笔记二

JUC学习笔记二

作者: Martain | 来源:发表于2020-07-13 17:22 被阅读0次

HashMap

HashMap类实现了Map接口,所以实现了Map常用的一些方法,Map通常在java开发中被称为字典,是一种保存数据的容器;HashMap是基于哈希表实现的,每一个元素是一个key-value对。HashMap在JDK1.8之前的实现方式 数组+链表,但是在JDK1.8后对HashMap进行了底层优化,改为了由 数组+链表+红黑树实现,主要的目的是提高查找效率。

HashTable

Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射;继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口,它的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。

HashMap VS HashTable

HashMap HashTable
线程安全
键值可为空
效率

HashTable为什么线程安全?

HashTable线程安全是因为它所有的函数都是线程同步的,即同时只允许一个线程在操作HashTable,这样保证了他的线程安全性,由于对整个HashTable都上了锁,导致当有线程在操作HashTable的时候,其他的线程会成阻塞状态,导致效率比较低下。

HashTable

ConCurrentHashMap

Java 5.0 在java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能。ConcurrentHashMap 同步容器类是Java 5增加的一个线程安全的哈希表。对与多线程的操作,介于 HashMap 与 Hashtable 之间。内部采用“锁分段”机制替代 Hashtable独占锁。进而提高性能。

此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetCopyOnWriteArrayListCopyOnWriteArraySet。当期望许多线程访问一个给定 collection 时, ConcurrentHashMap通常优于同步的HashMapConcurrentSkipListMap通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时, CopyOnWriteArrayList优于同步的ArrayList

ConCurrentHashMap

Java 8 中又将 ConCurrentHashMap锁分段机制改用了CAS算法来实现。因为CAS没有锁,不需要考虑上下文切换的问题,线程也不会阻塞,效率比较高。

并发修改异常

public class CopyOnWriteTest {
    public static void main(String[] args) {
        CopyOnWriteThread copyOnWriteThread = new CopyOnWriteThread();
        for (int i = 0; i < 10; i++) {
            new Thread(copyOnWriteThread,"线程"+(i+1)).start();
        }
    }
}

class CopyOnWriteThread implements Runnable{

    public static List<String> list = Collections.synchronizedList(new ArrayList<>());

    static {
        list.add("AA");
        list.add("BB");
        list.add("CC");
    }
    @Override
    public void run() {
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(Thread.currentThread().getName()+":"+iterator.next());
            list.add(Thread.currentThread().getName());
        }

    }
}

会报出java.util.ConcurrentModificationException异常

CopyOnWriteArrayList

public class CopyOnWriteTest {
    public static void main(String[] args) {
        CopyOnWriteThread copyOnWriteThread = new CopyOnWriteThread();
        for (int i = 0; i < 10; i++) {
            new Thread(copyOnWriteThread,"线程"+(i+1)).start();
        }
    }
}

class CopyOnWriteThread implements Runnable{

    public static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

    static {
        list.add("AA");
        list.add("BB");
        list.add("CC");
    }
    @Override
    public void run() {
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(Thread.currentThread().getName()+":"+iterator.next());
            list.add(Thread.currentThread().getName());
        }

    }
}

CopyOnWriteArrayList/CopyOnWriteArraySet "写入并复制" 每次写入都会复制一个新的列表,因为每次都要复制,所以效率比较低,如果要写入的操作比较多的话就不适用了。并发迭代多时可以适用。

闭锁(CountDownLatch)

闭锁:在完成某些运算时,只有其他所有的线程运算全部完成,当前运算才继续执行。

Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能。

CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行:

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
  • 等待直到某个操作所有参与者都准备就绪再继续执行。

实例:计算多个线程总耗费时间

public class CountDownLatchTest {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(10);
        LatchDemo latchDemo = new LatchDemo(latch);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            new Thread(latchDemo).start();
        }
        /**
         * 阻塞线程,等待
         */
        try {
            latch.await();
        }catch (InterruptedException e){

        }
        long end = System.currentTimeMillis();
        System.out.println("耗费时间为:"+(end-start));
    }
}

class LatchDemo implements Runnable{

    private CountDownLatch countDownLatch;

    public LatchDemo(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        try{
            for (int i = 0; i < 50000; i++) {
                if (i%10000==0){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        }finally {
            /**
             * latch减一
             */
            countDownLatch.countDown();
        }
    }
}

相关文章

  • JUC学习笔记二

    HashMap HashMap类实现了Map接口,所以实现了Map常用的一些方法,Map通常在java开发中被称为...

  • JUC学习笔记(二)—ConcurentHashMap

    Unsafe:是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Un...

  • ConcurrentSkipListMap 学习笔记

    ConcurrentSkipListMap 学习笔记 标签(空格分隔): juc学习 基于跳跃表的线程安全的map...

  • JUC 学习笔记

    JUC :package java.util.concurrent package java.util.con...

  • JUC学习笔记一

    什么是JUC 在 Java 5.0 (JDK 1.5)提供了 java.util.concurrent( 简称JU...

  • JUC学习笔记三

    JUC学习笔记三 用于解决多线程同步问题的方式 隐式锁(synchronized) 同步代码块 同步方法 显式锁(...

  • JUC学习笔记-锁

    1.为什么需要锁 解决多个线程访问同一个可变的状态变量时的安全问题。 2.内置锁 - synchronized 任...

  • JUC——检视阅读

    JUC——检视阅读 参考资料 JUC知识图参考 JUC框架学习顺序参考 J.U.C学习总结参考,简洁直观 易百并发...

  • JUC并发编程引导学习(超长篇)

    JUC并发编程学习 1、什么是JUC juc是Java并发编程的一个工具包,包名为java.util.concur...

  • 多线程学习笔记二之JUC组件

    概述 为了对共享资源提供更细粒度的同步控制,JDK5新增了java.util.concurrent(JUC)并发工...

网友评论

      本文标题:JUC学习笔记二

      本文链接:https://www.haomeiwen.com/subject/ephzcktx.html