java吧 关注:1,266,596贴子:12,773,219
  • 11回复贴,共1

学习Java并发技术,先从这个贴开始!

只看楼主收藏回复

Java并发编程一直是Java程序员必须懂但又是很难懂的技术内容。
这里不仅仅是指使用简单的多线程编程,或者使用juc的某个类。当然这些都是并发编程的基本知识,除了使用这些工具以外,Java并发编程中涉及到的技术原理十分丰富。为了更好地把并发知识形成一个体系,也鉴于本人没有能力写出这类文章,于是参考几位并发编程专家的博客和书籍,做一个简单的整理和复习。
本贴只是简要的介绍和总结。关注私信,会有更多的系列文章。


1楼2019-05-15 10:58回复
    并发基础和多线程
    首先需要学习的就是并发的基础知识,什么是并发,为什么要并发,多线程的概念,线程安全的概念等。
    然后学会使用Java中的Thread或是其他线程实现方法,了解线程的状态转换,线程的方法,线程的通信方式等。


    2楼2019-05-15 10:58
    回复
      2025-06-28 02:31:17
      广告
      JMM内存模型
      任何语言最终都是运行在处理器上,JVM虚拟机为了给开发者一个一致的编程内存模型,需要制定一套规则,这套规则可以在不同架构的机器上有不同实现,并且向上为程序员提供统一的JMM内存模型。
      所以了解JMM内存模型也是了解Java并发原理的一个重点,其中了解指令重排,内存屏障,以及可见性原理尤为重要。
      JMM只保证happens-before和as-if-serial规则,所以在多线程并发时,可能出现原子性,可见性以及有序性这三大问题。
      下面的内容则会讲述Java是如何解决这三大问题的。


      3楼2019-05-15 10:59
      回复
        synchronized,volatile,final等关键字
        对于并发的三大问题,volatile可以保证原子性和可见性,synchronized三种特性都可以保证(允许指令重排)。
        synchronized是基于操作系统的mutex lock指令实现的,volatile和final则是根据JMM实现其内存语义。
        此处还要了解CAS操作,它不仅提供了类似volatile的内存语义,并且保证操作原子性,因为它是由硬件实现的。
        JUC中的Lock底层就是使用volatile加上CAS的方式实现的。synchronized也会尝试用cas操作来优化器重量级锁。
        了解这些关键字是很有必要的。


        4楼2019-05-15 10:59
        回复
          JUC包
          在了解完上述内容以后,就可以看看JUC的内容了。
          JUC提供了包括Lock,原子操作类,线程池,同步容器,工具类等内容。
          这些类的基础都是AQS,所以了解AQS的原理是很重要的。
          除此之外,还可以了解一下Fork/Join,以及JUC的常用场景,比如生产者消费者,阻塞队列,以及读写容器等。


          5楼2019-05-15 10:59
          回复
            有空可以一起交流学习


            7楼2019-05-15 11:02
            回复
              来了


              来自Android客户端9楼2019-05-15 19:04
              回复
                第1部分 WeakHashMap介绍
                WeakHashMap简介
                WeakHashMap 继承于AbstractMap,实现了Map接口。
                和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对(key-value)映射,而且键和值都可以是null。
                不过WeakHashMap的键是“弱键”。在 WeakHashMap 中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。某个键被终止时,它对应的键值对也就从映射中有效地移除了。


                10楼2019-05-15 19:06
                回复
                  2025-06-28 02:25:17
                  广告
                  这个“弱键”的原理呢?大致上就是,通过WeakReference和ReferenceQueue实现的。 WeakHashMap的key是“弱键”,即是WeakReference类型的;ReferenceQueue是一个队列,它会保存被GC回收的“弱键”。实现步骤是:
                  (01) 新建WeakHashMap,将“键值对”添加到WeakHashMap中。
                  实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表。
                  (02) 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到ReferenceQueue(queue)队列中。


                  11楼2019-05-15 19:06
                  回复
                    03) 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的键值对;同步它们,就是删除table中被GC回收的键值对。
                    这就是“弱键”如何被自动从WeakHashMap中删除的步骤了。
                    和HashMap一样,WeakHashMap是不同步的。可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap。
                    WeakHashMap的构造函数
                    WeakHashMap共有4个构造函数,如下:
                    // 默认构造函数。
                    WeakHashMap()
                    // 指定“容量大小”的构造函数
                    WeakHashMap(int capacity)
                    // 指定“容量大小”和“加载因子”的构造函数
                    WeakHashMap(int capacity, float loadFactor)
                    // 包含“子Map”的构造函数
                    WeakHashMap(Map<? extends K, ? extends V> map)
                    WeakHashMap的API
                    void clear()
                    Object clone()
                    boolean containsKey(Object key)
                    boolean containsValue(Object value)
                    Set<Entry<K, V>> entrySet()
                    V get(Object key)
                    boolean isEmpty()
                    Set<K> keySet()
                    V put(K key, V value)
                    void putAll(Map<? extends K, ? extends V> map)
                    V remove(Object key)
                    int size()
                    Collection<V> values()


                    12楼2019-05-15 19:07
                    回复
                      第2部分 WeakHashMap数据结构
                      WeakHashMap的继承关系如下
                      java.lang.Object
                      ↳ java.util.AbstractMap<K, V>
                      ↳ java.util.WeakHashMap<K, V>
                      public class WeakHashMap<K,V>
                      extends AbstractMap<K,V>
                      implements Map<K,V> {}
                      WeakHashMap与Map关系如下图:
                      从图中可以看出:
                      (01) WeakHashMap继承于AbstractMap,并且实现了Map接口。
                      (02) WeakHashMap是哈希表,但是它的键是"弱键"。WeakHashMap中保护几个重要的成员变量:table, size, threshold, loadFactor, modCount, queue。
                      table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。
                      size是Hashtable的大小,它是Hashtable保存的键值对的数量。
                      threshold是Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值="容量*加载因子"。
                      loadFactor就是加载因子。
                      modCount是用来实现fail-fast机制的
                      queue保存的是“已被GC清除”的“弱引用的键”。
                      第3部分 WeakHashMap源码解析(基于JDK1.6.0_45)
                      下面对WeakHashMap的源码进行说明
                      View Code
                      说明:WeakHashMap和HashMap都是通过"拉链法"实现的散列表。它们的源码绝大部分内容都一样,这里就只是对它们不同的部分就是说明。
                      WeakReference是“弱键”实现的哈希表。它这个“弱键”的目的就是:实现对“键值对”的动态回收。当“弱键”不再被使用到时,GC会回收它,WeakReference也会将“弱键”对应的键值对删除。
                      “弱键”是一个“弱引用(WeakReference)”,在Java中,WeakReference和ReferenceQueue 是联合使用的。在WeakHashMap中亦是如此:如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。 接着,WeakHashMap会根据“引用队列”,来删除“WeakHashMap中已被GC回收的‘弱键’对应的键值对”。
                      另外,理解上面思想的重点是通过 expungeStaleEntries() 函数去理解。
                      第4部分 WeakHashMap遍历方式
                      4.1 遍历WeakHashMap的键值对
                      第一步:根据entrySet()获取WeakHashMap的“键值对”的Set集合。
                      第二步:通过Iterator迭代器遍历“第一步”得到的集合。
                      // 假设map是WeakHashMap对象
                      // map中的key是String类型,value是Integer类型
                      Integer integ = null;
                      Iterator iter = map.entrySet().iterator();
                      while(iter.hasNext()) {
                      Map.Entry entry = (Map.Entry)iter.next();
                      // 获取key
                      key = (String)entry.getKey();
                      // 获取value
                      integ = (Integer)entry.getValue();
                      }


                      13楼2019-05-15 19:08
                      回复
                        10万销量多久会被扣下来?


                        来自手机贴吧14楼2019-06-21 09:06
                        回复