当前位置: 首页 > news >正文

做电商网站商标湖南省网站备案登记

做电商网站商标,湖南省网站备案登记,网站关键字优化地点,典型网站建设线程安全集合类概述 重点介绍java.util.concurrent.* 下的线程安全集合类#xff0c;可以发现它们有规律#xff0c;里面包含三类关键词#xff1a;Blocking、CopyOnWrite、Concurrent Blocking 大部分实现基于锁#xff0c;并提供用来阻塞的方法 CopyOnWrite 之类容器修改…线程安全集合类概述 重点介绍java.util.concurrent.* 下的线程安全集合类可以发现它们有规律里面包含三类关键词Blocking、CopyOnWrite、Concurrent Blocking 大部分实现基于锁并提供用来阻塞的方法 CopyOnWrite 之类容器修改开销相对较重 Concurrent 类型的容器    内部很多操作使用 cas 优化一般可以提供较高吞吐量    弱一致性         遍历时弱一致性例如当利用迭代器遍历时如果容器发生修改迭代器仍然可以继续进行  遍历这时内容是旧的         求大小弱一致性size 操作未必是 100% 准确         读取弱一致性 遍历时如果发生了修改对于非安全容器来讲使用 fail-fast 机制也就是让遍历立刻失败抛出 ConcurrentModificationException不再继续遍历 ConcurrentHashMap原理 1. JDK 7 HashMap 并发死链 这得用jdk7才有效果我没有jdk7,就体会一下把 public static void main(String[] args) { // 测试 java 7 中哪些数字的 hash 结果相等System.out.println(长度为16时桶下标为1的key);for (int i 0; i 64; i) {if (hash(i) % 16 1) {System.out.println(i);}}System.out.println(长度为32时桶下标为1的key);for (int i 0; i 64; i) {if (hash(i) % 32 1) {System.out.println(i);}} // 1, 35, 16, 50 当大小为16时它们在一个桶内final HashMapInteger, Integer map new HashMapInteger, Integer(); // 放 12 个元素map.put(2, null);map.put(3, null);map.put(4, null);map.put(5, null);map.put(6, null);map.put(7, null);map.put(8, null);map.put(9, null);map.put(10, null);map.put(16, null);map.put(35, null);map.put(1, null);System.out.println(扩容前大小[main]:map.size());new Thread() {Overridepublic void run() { // 放第 13 个元素, 发生扩容map.put(50, null);System.out.println(扩容后大小[Thread-0]:map.size());}}.start();new Thread() {Overridepublic void run() { // 放第 13 个元素, 发生扩容map.put(50, null);System.out.println(扩容后大小[Thread-1]:map.size());}}.start();}final static int hash(Object k) {int h 0;if (0 ! h k instanceof String) {return sun.misc.Hashing.stringHash32((String) k);}h ^ k.hashCode();h ^ (h 20) ^ (h 12);return h ^ (h 7) ^ (h 4);} 原始链表格式[下标] (key,next) [1] (1,35)-(35,16)-(16,null) 线程 a 执行到 1 处 此时局部变量 e 为 (1,35)而局部变量 next 为 (35,16) 线程 a 挂起 线程 b 开始执行 第一次循环 [1] (1,null) 第二次循环 [1] (35,1)-(1,null) 第三次循环 [1] (35,1)-(1,null) [17] (16,null) 切换回线程 a此时局部变量 e 和 next 被恢复引用没变但内容变了e 的内容被改为 (1,null)而 next 的内 容被改为 (35,1) 并链向 (1,null) 第一次循环 [1] (1,null) 第二次循环注意这时 e 是 (35,1) 并链向 (1,null) 所以 next 又是 (1,null) [1] (35,1)-(1,null) 第三次循环e 是 (1,null)而 next 是 null但 e 被放入链表头这样 e.next 变成了 35 2 处 [1] (1,35)-(35,1)-(1,35) 已经是死链了 北 究其原因是因为在多线程环境下使用了非线程安全的 map 集合 JDK 8 虽然将扩容算法做了调整不再将元素加入链表头而是保持与扩容前一样的顺序但仍不意味着能够在多线程环境下能够安全扩容还会出现其它问题如扩容丢数据 2. JDK 8 ConcurrentHashMap 重要属性和内部类 // 默认为 0 // 当初始化时, 为 -1 // 当扩容时, 为 -(1 扩容线程数) // 当初始化或扩容完成后为 下一次的扩容的阈值大小 private transient volatile int sizeCtl; // 整个 ConcurrentHashMap 就是一个 Node[] static class NodeK,V implements Map.EntryK,V {} // hash 表 transient volatile NodeK,V[] table; // 扩容时的 新 hash 表 private transient volatile NodeK,V[] nextTable; // 扩容时如果某个 bin 迁移完毕, 用 ForwardingNode 作为旧 table bin 的头结点 static final class ForwardingNodeK,V extends NodeK,V {} // 用在 compute 以及 computeIfAbsent 时, 用来占位, 计算完成后替换为普通 Node static final class ReservationNodeK,V extends NodeK,V {} // 作为 treebin 的头节点, 存储 root 和 first static final class TreeBinK,V extends NodeK,V {} // 作为 treebin 的节点, 存储 parent, left, right static final class TreeNodeK,V extends NodeK,V {} 重要方法 // 获取 Node[] 中第 i 个 Node static final K,V NodeK,V tabAt(NodeK,V[] tab, int i) // cas 修改 Node[] 中第 i 个 Node 的值, c 为旧值, v 为新值 static final K,V boolean casTabAt(NodeK,V[] tab, int i, NodeK,V c, NodeK,V v) // 直接修改 Node[] 中第 i 个 Node 的值, v 为新值 static final K,V void setTabAt(NodeK,V[] tab, int i, NodeK,V v) 北 构造器分析 可以看到实现了懒惰初始化在构造方法中仅仅计算了 table 的大小以后在第一次使用时才会真正创建 public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { if (!(loadFactor 0.0f) || initialCapacity 0 || concurrencyLevel 0) throw new IllegalArgumentException(); if (initialCapacity concurrencyLevel) // Use at least as many bins initialCapacity concurrencyLevel; // as estimated threads long size (long)(1.0 (long)initialCapacity / loadFactor); // tableSizeFor 仍然是保证计算的大小是 2^n, 即 16,32,64 ... int cap (size (long)MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : tableSizeFor((int)size); this.sizeCtl cap; } get 流程全程没有加锁 public V get(Object key) { NodeK,V[] tab; NodeK,V e, p; int n, eh; K ek; // spread 方法能确保返回结果是正数 int h spread(key.hashCode()); if ((tab table) ! null (n tab.length) 0 (e tabAt(tab, (n - 1) h)) ! null) { // 如果头结点已经是要查找的 key if ((eh e.hash) h) { if ((ek e.key) key || (ek ! null key.equals(ek))) return e.val; } // hash 为负数表示该 bin 在扩容中或是 treebin, 这时调用 find 方法来查找 else if (eh 0) return (p e.find(h, key)) ! null ? p.val : null; // 正常遍历链表, 用 equals 比较 while ((e e.next) ! null) { if (e.hash h ((ek e.key) key || (ek ! null key.equals(ek)))) return e.val; } } return null; } put 流程真是令人头秃 public V put(K key, V value) { return putVal(key, value, false); } final V putVal(K key, V value, boolean onlyIfAbsent) { if (key null || value null) throw new NullPointerException(); // 其中 spread 方法会综合高位低位, 具有更好的 hash 性 int hash spread(key.hashCode()); int binCount 0; for (NodeK,V[] tab table;;) { // f 是链表头节点 // fh 是链表头结点的 hash // i 是链表在 table 中的下标 NodeK,V f; int n, i, fh; // 要创建 table if (tab null || (n tab.length) 0) // 初始化 table 使用了 cas, 无需 synchronized 创建成功, 进入下一轮循环 tab initTable(); // 要创建链表头节点 else if ((f tabAt(tab, i (n - 1) hash)) null) { // 添加链表头使用了 cas, 无需 synchronized if (casTabAt(tab, i, null, new NodeK,V(hash, key, value, null))) break; } // 帮忙扩容 else if ((fh f.hash) MOVED) // 帮忙之后, 进入下一轮循环 tab helpTransfer(tab, f); else { V oldVal null; // 锁住链表头节点 synchronized (f) { // 再次确认链表头节点没有被移动 if (tabAt(tab, i) f) { // 链表 if (fh 0) { binCount 1; // 遍历链表 for (NodeK,V e f;; binCount) { K ek; // 找到相同的 key if (e.hash hash ((ek e.key) key || (ek ! null key.equals(ek)))) { oldVal e.val; // 更新 if (!onlyIfAbsent) e.val value; break; } NodeK,V pred e; // 已经是最后的节点了, 新增 Node, 追加至链表尾 if ((e e.next) null) { pred.next new NodeK,V(hash, key, value, null); break; } } } // 红黑树 else if (f instanceof TreeBin) { NodeK,V p; binCount 2; // putTreeVal 会看 key 是否已经在树中, 是, 则返回对应的 TreeNode if ((p ((TreeBinK,V)f).putTreeVal(hash, key, value)) ! null) { oldVal p.val; if (!onlyIfAbsent) p.val value; } } } // 释放链表头节点的锁 } if (binCount ! 0) { if (binCount TREEIFY_THRESHOLD) // 如果链表长度 树化阈值(8), 进行链表转为红黑树 treeifyBin(tab, i); if (oldVal ! null) return oldVal; break; } } } // 增加 size 计数 addCount(1L, binCount); return null; } private final NodeK,V[] initTable() { NodeK,V[] tab; int sc; while ((tab table) null || tab.length 0) { if ((sc sizeCtl) 0) Thread.yield(); // 尝试将 sizeCtl 设置为 -1表示初始化 table else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { // 获得锁, 创建 table, 这时其它线程会在 while() 循环中 yield 直至 table 创建 try { if ((tab table) null || tab.length 0) { int n (sc 0) ? sc : DEFAULT_CAPACITY; NodeK,V[] nt (NodeK,V[])new Node?,?[n]; table tab nt; sc n - (n 2); } } finally { sizeCtl sc; } break; } } return tab; } // check 是之前 binCount 的个数 private final void addCount(long x, int check) { CounterCell[] as; long b, s; if ( // 已经有了 counterCells, 向 cell 累加 (as counterCells) ! null || // 还没有, 向 baseCount 累加 !U.compareAndSwapLong(this, BASECOUNT, b baseCount, s b x) ) { CounterCell a; long v; int m; boolean uncontended true; if ( // 还没有 counterCells as null || (m as.length - 1) 0 || // 还没有 cell (a as[ThreadLocalRandom.getProbe() m]) null || // cell cas 增加计数失败 !(uncontended U.compareAndSwapLong(a, CELLVALUE, v a.value, v x)) ) { // 创建累加单元数组和cell, 累加重试 fullAddCount(x, uncontended); return; } if (check 1) return; // 获取元素个数 s sumCount(); } if (check 0) { NodeK,V[] tab, nt; int n, sc; while (s (long)(sc sizeCtl) (tab table) ! null (n tab.length) MAXIMUM_CAPACITY) { int rs resizeStamp(n); if (sc 0) { if ((sc RESIZE_STAMP_SHIFT) ! rs || sc rs 1 || sc rs MAX_RESIZERS || (nt nextTable) null || transferIndex 0) break; // newtable 已经创建了帮忙扩容 if (U.compareAndSwapInt(this, SIZECTL, sc, sc 1)) transfer(tab, nt); } // 需要扩容这时 newtable 未创建 else if (U.compareAndSwapInt(this, SIZECTL, sc, (rs RESIZE_STAMP_SHIFT) 2)) transfer(tab, null); s sumCount(); } } } size 计算流程 size 计算实际发生在 putremove 改变集合元素的操作之中       没有竞争发生向 baseCount 累加计数       有竞争发生新建 counterCells向其中的一个 cell 累加计数           counterCells 初始有两个 cell           如果计数竞争比较激烈会创建新的 cell 来累加计数 public int size() { long n sumCount(); return ((n 0L) ? 0 : (n (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)n); } final long sumCount() { CounterCell[] as counterCells; CounterCell a; // 将 baseCount 计数与所有 cell 计数累加 long sum baseCount; if (as ! null) { for (int i 0; i as.length; i) { if ((a as[i]) ! null) sum a.value; } } return sum; } Java 8 数组Node 链表 Node | 红黑树 TreeNode 以下数组简称table链表简称bin 初始化使用 cas 来保证并发安全懒惰初始化 table 树化当 table.length 64 时先尝试扩容超过 64 时并且 bin.length 8 时会将链表树化树化过程会用 synchronized 锁住链表头 put如果该 bin 尚未创建只需要使用 cas 创建 bin如果已经有了锁住链表头进行后续 put 操作元素添加至 bin 的尾部 get无锁操作仅需要保证可见性扩容过程中 get 操作拿到的是 ForwardingNode 它会让 get 操作在新table 进行搜索 扩容扩容时以 bin 为单位进行需要对 bin 进行 synchronized但这时妙的是其它竞争线程也不是无事可做它们会帮助把其它 bin 进行扩容扩容时平均只有 1/6 的节点会把复制到新 table 中 size元素个数保存在 baseCount 中并发时的个数变动保存在 CounterCell[] 当中。最后统计数量时累加即可 LinkedBlockingQueue 原理 public class LinkedBlockingQueueE extends AbstractQueueE implements BlockingQueueE, java.io.Serializable { static class NodeE { E item; /** * 下列三种情况之一 * - 真正的后继节点 * - 自己, 发生在出队时 * - null, 表示是没有后继节点, 是最后了 */ NodeE next; Node(E x) { item x; } } } 初始化链表 last head new NodeE(null); Dummy 节点用来占位item 为 null 当一个节点入队 last last.next node; 再来一个节点入队 last last.next node; 出队 NodeE h head; NodeE first h.next; h.next h; // help GC head first; E x first.item; first.item null; return x; h head first h.next h.next h head first E x first.item; first.item null; return x; 加锁分析 高明之处在于用了两把锁和 dummy 节点     用一把锁同一时刻最多只允许有一个线程生产者或消费者二选一执行     用两把锁同一时刻可以允许两个线程同时一个生产者与一个消费者执行         消费者与消费者线程仍然串行         生产者与生产者线程仍然串行 线程安全分析 当节点总数大于 2 时包括 dummy 节点putLock 保证的是 last 节点的线程安全takeLock 保证的是head 节点的线程安全。两把锁保证了入队和出队没有竞争 当节点总数等于 2 时即一个 dummy 节点一个正常节点这时候仍然是两把锁锁两个对象不会竞争 当节点总数等于 1 时就一个 dummy 节点这时 take 线程会被 notEmpty 条件阻塞有竞争会阻塞 put 操作 public void put(E e) throws InterruptedException { if (e null) throw new NullPointerException(); int c -1; NodeE node new NodeE(e); final ReentrantLock putLock this.putLock; // count 用来维护元素计数 final AtomicInteger count this.count; putLock.lockInterruptibly(); try { // 满了等待 while (count.get() capacity) { // 倒过来读就好: 等待 notFull notFull.await(); } // 有空位, 入队且计数加一 enqueue(node); c count.getAndIncrement(); // 除了自己 put 以外, 队列还有空位, 由自己叫醒其他 put 线程 if (c 1 capacity) notFull.signal(); } finally { putLock.unlock(); } // 如果队列中有一个元素, 叫醒 take 线程 if (c 0) // 这里调用的是 notEmpty.signal() 而不是 notEmpty.signalAll() 是为了减少竞争 signalNotEmpty(); } take 操作 public E take() throws InterruptedException { E x; int c -1; final AtomicInteger count this.count; final ReentrantLock takeLock this.takeLock; takeLock.lockInterruptibly(); try { while (count.get() 0) { notEmpty.await(); } x dequeue(); c count.getAndDecrement(); if (c 1) notEmpty.signal(); } finally { takeLock.unlock(); } // 如果队列中只有一个空位时, 叫醒 put 线程 // 如果有多个线程进行出队, 第一个线程满足 c capacity, 但后续线程 c capacity if (c capacity) // 这里调用的是 notFull.signal() 而不是 notFull.signalAll() 是为了减少竞争 signalNotFull() return x; } LinkedBlockingQueue 与 ArrayBlockingQueue 的性能比较 Linked 支持有界Array 强制有界 Linked 实现是链表Array 实现是数组 Linked 是懒惰的而 Array 需要提前初始化 Node 数组 Linked 每次入队会生成新 Node而 Array 的 Node 是提前创建好的 Linked 两把锁Array 一把锁
文章转载自:
http://www.morning.mgskc.cn.gov.cn.mgskc.cn
http://www.morning.gltmz.cn.gov.cn.gltmz.cn
http://www.morning.grbgn.cn.gov.cn.grbgn.cn
http://www.morning.wnqbf.cn.gov.cn.wnqbf.cn
http://www.morning.lgqdl.cn.gov.cn.lgqdl.cn
http://www.morning.jfcbs.cn.gov.cn.jfcbs.cn
http://www.morning.wmdqc.com.gov.cn.wmdqc.com
http://www.morning.shuangxizhongxin.cn.gov.cn.shuangxizhongxin.cn
http://www.morning.hphrz.cn.gov.cn.hphrz.cn
http://www.morning.qwdqq.cn.gov.cn.qwdqq.cn
http://www.morning.cqyhdy.cn.gov.cn.cqyhdy.cn
http://www.morning.wfyqn.cn.gov.cn.wfyqn.cn
http://www.morning.tstwx.cn.gov.cn.tstwx.cn
http://www.morning.rnrwq.cn.gov.cn.rnrwq.cn
http://www.morning.ptmch.com.gov.cn.ptmch.com
http://www.morning.chongzhanggui.cn.gov.cn.chongzhanggui.cn
http://www.morning.tsnmt.cn.gov.cn.tsnmt.cn
http://www.morning.lbbyx.cn.gov.cn.lbbyx.cn
http://www.morning.fycjx.cn.gov.cn.fycjx.cn
http://www.morning.fgkwh.cn.gov.cn.fgkwh.cn
http://www.morning.ktrzt.cn.gov.cn.ktrzt.cn
http://www.morning.c7491.cn.gov.cn.c7491.cn
http://www.morning.mhnr.cn.gov.cn.mhnr.cn
http://www.morning.pzqnj.cn.gov.cn.pzqnj.cn
http://www.morning.rfjmy.cn.gov.cn.rfjmy.cn
http://www.morning.rlxnc.cn.gov.cn.rlxnc.cn
http://www.morning.xwnnp.cn.gov.cn.xwnnp.cn
http://www.morning.shinezoneserver.com.gov.cn.shinezoneserver.com
http://www.morning.qmfhh.cn.gov.cn.qmfhh.cn
http://www.morning.dwyyf.cn.gov.cn.dwyyf.cn
http://www.morning.ljfjm.cn.gov.cn.ljfjm.cn
http://www.morning.wsgyq.cn.gov.cn.wsgyq.cn
http://www.morning.cjmmn.cn.gov.cn.cjmmn.cn
http://www.morning.rntyn.cn.gov.cn.rntyn.cn
http://www.morning.ntqqm.cn.gov.cn.ntqqm.cn
http://www.morning.rnzgf.cn.gov.cn.rnzgf.cn
http://www.morning.syssdz.cn.gov.cn.syssdz.cn
http://www.morning.rwtlj.cn.gov.cn.rwtlj.cn
http://www.morning.jnptt.cn.gov.cn.jnptt.cn
http://www.morning.qpzjh.cn.gov.cn.qpzjh.cn
http://www.morning.dgsr.cn.gov.cn.dgsr.cn
http://www.morning.nnjq.cn.gov.cn.nnjq.cn
http://www.morning.qmrsf.cn.gov.cn.qmrsf.cn
http://www.morning.nypgb.cn.gov.cn.nypgb.cn
http://www.morning.ejknty.cn.gov.cn.ejknty.cn
http://www.morning.wnhml.cn.gov.cn.wnhml.cn
http://www.morning.yaqi6.com.gov.cn.yaqi6.com
http://www.morning.kzcfp.cn.gov.cn.kzcfp.cn
http://www.morning.mbdbe.cn.gov.cn.mbdbe.cn
http://www.morning.knngw.cn.gov.cn.knngw.cn
http://www.morning.mdjtk.cn.gov.cn.mdjtk.cn
http://www.morning.kjfsd.cn.gov.cn.kjfsd.cn
http://www.morning.ygkb.cn.gov.cn.ygkb.cn
http://www.morning.zlff.cn.gov.cn.zlff.cn
http://www.morning.pxbky.cn.gov.cn.pxbky.cn
http://www.morning.gpkjx.cn.gov.cn.gpkjx.cn
http://www.morning.dnzyx.cn.gov.cn.dnzyx.cn
http://www.morning.dnconr.cn.gov.cn.dnconr.cn
http://www.morning.lzsxp.cn.gov.cn.lzsxp.cn
http://www.morning.flmxl.cn.gov.cn.flmxl.cn
http://www.morning.bfybb.cn.gov.cn.bfybb.cn
http://www.morning.bsjpd.cn.gov.cn.bsjpd.cn
http://www.morning.drkk.cn.gov.cn.drkk.cn
http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn
http://www.morning.rpms.cn.gov.cn.rpms.cn
http://www.morning.fphbz.cn.gov.cn.fphbz.cn
http://www.morning.glncb.cn.gov.cn.glncb.cn
http://www.morning.dhwyl.cn.gov.cn.dhwyl.cn
http://www.morning.pbsfq.cn.gov.cn.pbsfq.cn
http://www.morning.wztlr.cn.gov.cn.wztlr.cn
http://www.morning.mcjxq.cn.gov.cn.mcjxq.cn
http://www.morning.jrlxz.cn.gov.cn.jrlxz.cn
http://www.morning.kltsn.cn.gov.cn.kltsn.cn
http://www.morning.qtqk.cn.gov.cn.qtqk.cn
http://www.morning.rnzwh.cn.gov.cn.rnzwh.cn
http://www.morning.gxwyr.cn.gov.cn.gxwyr.cn
http://www.morning.fhsgw.cn.gov.cn.fhsgw.cn
http://www.morning.qzsmz.cn.gov.cn.qzsmz.cn
http://www.morning.mmtjk.cn.gov.cn.mmtjk.cn
http://www.morning.wmrgp.cn.gov.cn.wmrgp.cn
http://www.tj-hxxt.cn/news/219510.html

相关文章:

  • 织梦怎么做淘客网站深汕特别合作区面积
  • 在线代理浏览网站营销型网站建设步骤
  • 龙岗外贸网站建设公司互联网保险的优势
  • 法治建设的网站石家庄网络平台推广
  • 网站建设公司市场开发方案做网站哪个语言好
  • 电影vip网站建设步骤电气工程师报考条件
  • 汉子由来 外国人做的网站怎么做国外网上生意
  • 手机怎么创网站网站建设涉及到哪些方面
  • 快站心动小程序官网wordpress get_attached_media
  • 有哪些可以免费推广的网站起名网站开发
  • 如何做二维码跳转到网站iis 网站名
  • 盗用别的公司网站模块中国外协加工网最新订单
  • 衡水建网站的公司一般家庭装修照片
  • 国外免费网站服务器链接做茶叶网站
  • 中小企业网站建设多少钱民治做网站
  • 没有网站怎么做网络推广百度竞价推广开户价格
  • 网站推广广告大航母网站建设费用
  • 拿网站做商标教育类app开发
  • 全网推广网站深圳创业扶持政策
  • 网站开发需要哪些流程网站建设合同技术开发合同范本
  • 手机在线做ppt模板下载网站织梦cms收费不交有事吗
  • 锋云科技网站建设网络网站
  • 中英文切换的网站怎么做制作网页的视频教程
  • 杭州正晖建设工程有限公司网站一般通过唾液传染的疾病有哪些
  • 网站建设公司 选中企动力公司建设宁夏分行互联网站
  • 缺乏门户网站建设wordpress全端美化
  • 网站推广优化公司注册公司每年需要缴纳什么费用
  • 建网站主机灌南网站定制
  • 黑龙江省和城乡建设厅网站wordpress去除幻灯片
  • 崂山网站建设运营一个app大概多少钱