ConcurrentHashMap 源码分析03之内部类ForEachTask、SearchTask

此处的内部类很多类似,这里只解释 ForEachEntryTask、ForEachTransformedEntryTask、SearchMappingsTask。

1.3.22 BulkTask

  • 处理批量任务,众多子类,基本上包含Task的内部类就是其子类
abstract static class BulkTask<K,V,R> extends CountedCompleter<R> {
    Node<K,V>[] tab;        // tab 数组
    Node<K,V> next;			// 下一节点
    /* stack: 栈顶结点, spare: 备用节点,相当于中继节点 */
    TableStack<K,V> stack, spare;
    int index; // 索引下标
    int baseIndex; // 上界
    int baseLimit; // 下界
    final int baseSize; // 个数
    int batch;              // 并行批量处理个数(但不等同于线程个数)
	/* 构造函数:指定各种属性值 */
    BulkTask(BulkTask<K,V,?> par, int b, int i, int f, Node<K,V>[] t) {
        super(par);
        this.batch = b;
        this.index = this.baseIndex = i;
        /* 不同情况指定不同上界 */
        if ((this.tab = t) == null)
            this.baseSize = this.baseLimit = 0;
        else if (par == null)
            this.baseSize = this.baseLimit = t.length;
        else {
            this.baseLimit = f;
            this.baseSize = par.baseSize;
        }
    }

    /* 获取下一元素,不存在则返回null */
    /* 这里如果遇到扩容,存储当前状态pushState(t, i, n),等到扩容完成后,取出状态recoverState(n) */
    final Node<K,V> advance() {
        Node<K,V> e;
        /* 如果已经进入了一个非空的hash桶,直接尝试获取它的下一个节点 */
        if ((e = next) != null)
            e = e.next;
        for (;;) {
            Node<K,V>[] t; int i, n;  // must use locals in checks
            /* 下一节点不为 null,直接返回 */
            if (e != null)
                return next = e;
            /* 下界 >= 上界 || tab数组为空 || tab数组长度 <= 下界 || index < 0,没有新桶,返回 null  */    
            if (baseIndex >= baseLimit || (t = tab) == null ||
                (n = t.length) <= (i = index) || i < 0)
                return next = null;
            /* 桶位元素存在 && hash值 < 0,若此时为链表节点,e 已经赋值完毕 */    
            if ((e = tabAt(t, i)) != null && e.hash < 0) {
            	/* 是否为移动节点(正在扩容) */
                if (e instanceof ForwardingNode) {
                    tab = ((ForwardingNode<K,V>)e).nextTable;
                    e = null;
                    pushState(t, i, n); // 保存当前遍历状态
                    continue;
                }
                else if (e instanceof TreeBin)
                    e = ((TreeBin<K,V>)e).first; // 返回树的首节点
                else
                    e = null;
            }
            /* 弹出存储状态 */
            if (stack != null)
                recoverState(n);
            else if ((index = i + baseSize) >= n)
                index = ++baseIndex; // 这里的主要作用是 index++ 即指针往前移一位
        }
    }
	/* 保存当前遍历状态 */
    private void pushState(Node<K,V>[] t, int i, int n) {
        TableStack<K,V> s = spare;  // spare备用,减少 new 对象
        if (s != null)
            spare = s.next;
        else
            s = new TableStack<K,V>();
        s.tab = t;
        s.length = n;
        s.index = i;
        s.next = stack;
        stack = s;
    }

    /* 恢复存储时的状态 */
    private void recoverState(int n) {
        TableStack<K,V> s; int len;
        /* (index += (len = s.length)) >= n 这里的作用是 获取 tab[i+n] 位置的值 */
        while ((s = stack) != null && (index += (len = s.length)) >= n) {
        	/* 恢复成保存时的状态,以此循环尚未遍历的后序的值 */
        	/* 从这里可以看到,若添加在扩容前[index ~ len-1]后的值,可以遍历的到,但桶位之前的值不会遍历 */
            n = len;
            index = s.index;
            tab = s.tab;
            s.tab = null;
            /* stack 后移,存储spare备用 */
            TableStack<K,V> next = s.next;
            s.next = spare;
            stack = next;
            spare = s;
        }
        /* 获取完 stack 后,index指针后移 */
        if (s == null && (index += baseSize) >= n)
            index = ++baseIndex;
    }
}

1.3.23 ForEachKeyTask

  • 遍历 key 的任务
@SuppressWarnings("serial")
static final class ForEachKeyTask<K,V>
    extends BulkTask<K,V,Void> {
    final Consumer<? super K> action;
    ForEachKeyTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Consumer<? super K> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    public final void compute() {
        final Consumer<? super K> action;
        if ((action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachKeyTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null;)
                action.accept(p.key);
            propagateCompletion();
        }
    }
}

1.3.24 ForEachValueTask

  • 遍历 value 的任务
@SuppressWarnings("serial")
static final class ForEachValueTask<K,V>
    extends BulkTask<K,V,Void> {
    final Consumer<? super V> action;
    ForEachValueTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Consumer<? super V> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    public final void compute() {
        final Consumer<? super V> action;
        if ((action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachValueTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null;)
                action.accept(p.val);
            propagateCompletion();
        }
    }
}

1.3.25 ForEachEntryTask

  • 遍历 entry 的任务,继承 BulkTask
@SuppressWarnings("serial")
static final class ForEachEntryTask<K,V>
    extends BulkTask<K,V,Void> {
    final Consumer<? super Entry<K,V>> action; // 传入的 action 动作
    ForEachEntryTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Consumer<? super Entry<K,V>> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    /* 执行遍历的真正的方法 */
    public final void compute() {
        final Consumer<? super Entry<K,V>> action;
        /* action 为 null 没必要进行操作 */
        if ((action = this.action) != null) {
        	/* 这里为循环分解任务,fork 为在池中添加任务 */
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1); // 分任务 + 1
                new ForEachEntryTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            /* 遍历本任务的含有的所有元素 */
            for (Node<K,V> p; (p = advance()) != null; )
                action.accept(p);
            propagateCompletion(); // 是否所有分任务都执行完成
        }
    }
}

1.3.26 ForEachMappingTask

    • 遍历 map 的任务
@SuppressWarnings("serial")
static final class ForEachMappingTask<K,V>
    extends BulkTask<K,V,Void> {
    final BiConsumer<? super K, ? super V> action;
    ForEachMappingTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         BiConsumer<? super K,? super V> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    public final void compute() {
        final BiConsumer<? super K, ? super V> action;
        if ((action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachMappingTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; )
                action.accept(p.key, p.val);
            propagateCompletion();
        }
    }
}

1.3.27 ForEachTransformedKeyTask

  • 遍历 转换key 的任务,相当于对key做一定的更换,在执行 action 动作
@SuppressWarnings("serial")
static final class ForEachTransformedKeyTask<K,V,U>
    extends BulkTask<K,V,Void> {
    final Function<? super K, ? extends U> transformer;
    final Consumer<? super U> action;
    ForEachTransformedKeyTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<? super K, ? extends U> transformer, Consumer<? super U> action) {
        super(p, b, i, f, t);
        this.transformer = transformer; this.action = action;
    }
    public final void compute() {
        final Function<? super K, ? extends U> transformer;
        final Consumer<? super U> action;
        if ((transformer = this.transformer) != null &&
            (action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachTransformedKeyTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     transformer, action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; ) {
                U u;
                if ((u = transformer.apply(p.key)) != null)
                    action.accept(u);
            }
            propagateCompletion();
        }
    }
}

1.3.28 ForEachTransformedValueTask

  • 遍历转换value的任务,相当于对value 做一定的更换,在执行 action 动作
@SuppressWarnings("serial")
static final class ForEachTransformedValueTask<K,V,U>
    extends BulkTask<K,V,Void> {
    final Function<? super V, ? extends U> transformer;
    final Consumer<? super U> action;
    ForEachTransformedValueTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<? super V, ? extends U> transformer, Consumer<? super U> action) {
        super(p, b, i, f, t);
        this.transformer = transformer; this.action = action;
    }
    public final void compute() {
        final Function<? super V, ? extends U> transformer;
        final Consumer<? super U> action;
        if ((transformer = this.transformer) != null &&
            (action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachTransformedValueTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     transformer, action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; ) {
                U u;
                if ((u = transformer.apply(p.val)) != null)
                    action.accept(u);
            }
            propagateCompletion();
        }
    }
}

1.3.29 ForEachTransformedEntryTask

  • 遍历 转换entry 的任务,相当于对 entry 做一定的更换,在执行 action 动作
@SuppressWarnings("serial")
staticfinal class ForEachTransformedEntryTask<K,V,U>
    extends BulkTask<K,V,Void> {
    final Function<Map.Entry<K,V>, ? extends U> transformer;
    final Consumer<? super U> action;
    /* 构造函数:初始化属性 */
    ForEachTransformedEntryTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<Map.Entry<K,V>, ? extends U> transformer, Consumer<? super U> action) {
        super(p, b, i, f, t);
        this.transformer = transformer; this.action = action;
    }
    /* 真正执行遍历的方法 */
    public final void compute() {
        final Function<Map.Entry<K,V>, ? extends U> transformer;
        final Consumer<? super U> action;
        /* 分解任务的方法 */
        if ((transformer = this.transformer) != null &&
            (action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1); // 分任务 + 1
                new ForEachTransformedEntryTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     transformer, action).fork();
            }
            /* 遍历所有本任务的元素,accept方法 接收的参数 u 为 transformer返回的对象 */
            for (Node<K,V> p; (p = advance()) != null; ) {
                U u;
                if ((u = transformer.apply(p)) != null)
                    action.accept(u);
            }
            propagateCompletion(); // 是否所有分任务都完成
        }
    }
}

1.3.30 ForEachTransformedMappingTask

  • 遍历 转换map元素 的任务,相当于对map元素做一定的更换,在执行 action 动作
@SuppressWarnings("serial")
static final class ForEachTransformedMappingTask<K,V,U>
    extends BulkTask<K,V,Void> {
    final BiFunction<? super K, ? super V, ? extends U> transformer;
    final Consumer<? super U> action;
    ForEachTransformedMappingTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         BiFunction<? super K, ? super V, ? extends U> transformer,
         Consumer<? super U> action) {
        super(p, b, i, f, t);
        this.transformer = transformer; this.action = action;
    }
    public final void compute() {
        final BiFunction<? super K, ? super V, ? extends U> transformer;
        final Consumer<? super U> action;
        if ((transformer = this.transformer) != null &&
            (action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachTransformedMappingTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     transformer, action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; ) {
                U u;
                if ((u = transformer.apply(p.key, p.val)) != null)
                    action.accept(u);
            }
            propagateCompletion();
        }
    }
}

1.3.31 SearchKeysTask

  • 查找 keys 的任务
@SuppressWarnings("serial")
static final class SearchKeysTask<K,V,U>
    extends BulkTask<K,V,U> {
    /* 查找方法 */
    final Function<? super K, ? extends U> searchFunction;
    final AtomicReference<U> result;
    SearchKeysTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<? super K, ? extends U> searchFunction,
         AtomicReference<U> result) {
        super(p, b, i, f, t);
        this.searchFunction = searchFunction; this.result = result;
    }
    public final U getRawResult() { return result.get(); }
    public final void compute() {
        final Function<? super K, ? extends U> searchFunction;
        final AtomicReference<U> result;
        if ((searchFunction = this.searchFunction) != null &&
            (result = this.result) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                if (result.get() != null)
                    return;
                addToPendingCount(1);
                new SearchKeysTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     searchFunction, result).fork();
            }
            while (result.get() == null) {
                U u;
                Node<K,V> p;
                if ((p = advance()) == null) {
                    propagateCompletion();
                    break;
                }
                if ((u = searchFunction.apply(p.key)) != null) {
                    if (result.compareAndSet(null, u))
                        quietlyCompleteRoot();
                    break;
                }
            }
        }
    }
}

1.3.32 SearchValuesTask

    • 查找 values的任务
@SuppressWarnings("serial")
static final class SearchValuesTask<K,V,U>
    extends BulkTask<K,V,U> {
    final Function<? super V, ? extends U> searchFunction;
    final AtomicReference<U> result;
    SearchValuesTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<? super V, ? extends U> searchFunction,
         AtomicReference<U> result) {
        super(p, b, i, f, t);
        this.searchFunction = searchFunction; this.result = result;
    }
    public final U getRawResult() { return result.get(); }
    public final void compute() {
        final Function<? super V, ? extends U> searchFunction;
        final AtomicReference<U> result;
        if ((searchFunction = this.searchFunction) != null &&
            (result = this.result) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                if (result.get() != null)
                    return;
                addToPendingCount(1);
                new SearchValuesTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     searchFunction, result).fork();
            }
            while (result.get() == null) {
                U u;
                Node<K,V> p;
                if ((p = advance()) == null) {
                    propagateCompletion();
                    break;
                }
                if ((u = searchFunction.apply(p.val)) != null) {
                    if (result.compareAndSet(null, u))
                        quietlyCompleteRoot();
                    break;
                }
            }
        }
    }
}

1.3.33 SearchEntriesTask

  • 查找 entries 的任务
@SuppressWarnings("serial")
static final class SearchEntriesTask<K,V,U>
    extends BulkTask<K,V,U> {
    final Function<Entry<K,V>, ? extends U> searchFunction;
    final AtomicReference<U> result;
    SearchEntriesTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Function<Entry<K,V>, ? extends U> searchFunction,
         AtomicReference<U> result) {
        super(p, b, i, f, t);
        this.searchFunction = searchFunction; this.result = result;
    }
    public final U getRawResult() { return result.get(); }
    public final void compute() {
        final Function<Entry<K,V>, ? extends U> searchFunction;
        final AtomicReference<U> result;
        if ((searchFunction = this.searchFunction) != null &&
            (result = this.result) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                if (result.get() != null)
                    return;
                addToPendingCount(1);
                new SearchEntriesTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     searchFunction, result).fork();
            }
            while (result.get() == null) {
                U u;
                Node<K,V> p;
                if ((p = advance()) == null) {
                    propagateCompletion();
                    break;
                }
                if ((u = searchFunction.apply(p)) != null) {
                    if (result.compareAndSet(null, u))
                        quietlyCompleteRoot();
                    return;
                }
            }
        }
    }
}

1.3.34 SearchMappingsTask

    • 查找 mappings 的任务
@SuppressWarnings("serial")
static final class SearchMappingsTask<K,V,U>
    extends BulkTask<K,V,U> {
    final BiFunction<? super K, ? super V, ? extends U> searchFunction;
    final AtomicReference<U> result;
    /* 构造函数:初始化属性值 */
    SearchMappingsTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         BiFunction<? super K, ? super V, ? extends U> searchFunction,
         AtomicReference<U> result) {
        super(p, b, i, f, t);
        this.searchFunction = searchFunction; this.result = result;
    }
    /* 获取结果值 */
    public final U getRawResult() { return result.get(); }
    /* 分解并遍历元素的方法 */
    public final void compute() {
        final BiFunction<? super K, ? super V, ? extends U> searchFunction;
        final AtomicReference<U> result;
        /* searchFunction || result 为null 则没必要继续 */
        if ((searchFunction = this.searchFunction) != null &&
            (result = this.result) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                /* 已有结果,直接返回 */     
                if (result.get() != null)
                    return;
                addToPendingCount(1); // 分任务 + 1
                new SearchMappingsTask<K,V,U>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     searchFunction, result).fork();
            }
            /* 结果为null则循环遍历当前任务的所有元素 */
            while (result.get() == null) {
                U u;
                Node<K,V> p;
                /* 当前任务所有元素遍历完成 */
                if ((p = advance()) == null) {
                    propagateCompletion(); // 查看其他分任务是否成功完成任务
                    break;
                }
                /* 找到符合的元素 */
                if ((u = searchFunction.apply(p.key, p.val)) != null) {
                	/* CAS 设置 result */
                    if (result.compareAndSet(null, u))
                        quietlyCompleteRoot(); // 盲猜应该是设置查找任务完成
                    break;
                }
            }
        }
    }
}
ConcurrentHashMapJava中的一个并发容器,用于在多线程环境中安全地存储和访问键值对。它使用了一些特殊的技术来提高其并发性能。 ConcurrentHashMap源码分析可以从几个关键点开始。首先,它使用了大量的CAS(Compare and Swap)操作来代替传统的重量级锁操作,从而提高了并发性能。只有在节点实际变动的过程中才会进行加锁操作,这样可以减少对整个容器的锁竞争。 其次,ConcurrentHashMap的数据结构是由多个Segment组成的,每个Segment又包含多个HashEntry。这样的设计使得在多线程环境下,不同的线程可以同时对不同的Segment进行操作,从而提高了并发性能。每个Segment都相当于一个独立的HashMap,有自己的锁来保证线程安全。 在JDK1.7版本中,ConcurrentHashMap采用了分段锁的设计,即每个Segment都有自己的锁。这样的设计可以在多线程环境下提供更好的并发性能,因为不同的线程可以同时对不同的Segment进行读写操作,从而减少了锁竞争。 总的来说,ConcurrentHashMap通过使用CAS操作、分段锁以及特定的数据结构来实现线程安全的并发访问。这使得它成为在多线程环境中高效地存储和访问键值对的选择。123 #### 引用[.reference_title] - *1* [ConcurrentHashMap 源码解析](https://blog.csdn.net/Vampirelzl/article/details/126548972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* *3* [ConcurrentHashMap源码分析](https://blog.csdn.net/java123456111/article/details/124883950)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值