最近在学习pomelo的时候,偶然在网上看到博文《史上最强算法论战:请不要嘻哈,这是哈希》
http://chuansong.me/n/1489885
被作者的文笔吸引,对其中的干货很有兴趣,随后用一周时间进行了膜拜。现将学习结果总结如下。
[list]
[*]1.所谓无锁设计,是不使用编程语言的多线程锁转而使用cpu的锁(总线锁,寄存器锁,缓存锁)
[*]2.CAS原语有好多种写法,目前的物理服务器都是多cpu多核心,所以需要按Test and test and set 的写法编程。
[*]3.当前的现代cpu,Cache Line 是64byte .机器的字长是64bit.cpu只对16,32,64 bit的数据提供原子操作。
[/list]

未解决的问题:这货到底是用在什么业务场景的,一直没想明白,所以也没办法写出来测试程序。请iteye上的大师指点。

package testPatternBox;

import java.util.concurrent.atomic.AtomicLong;import java.util.concurrent.locks.LockSupport;

class BackOffAtomicLong{

    private final AtomicLong value = new AtomicLong ( 0L );

    public long get ( )   {     return value.get ( ); }

   public long incrementAndGet ( )   {     for ( ;; )        {         long current = get ( );          long next = current + 1;            if ( compareAndSet (    current ,                                 next ) )              return next;      } }

   public long subtractAndGet ( )    {     for ( ;; )        {         long current = get ( );          long next = current - 1;         if ( compareAndSet (    current ,                                 next ) )              return next;      } }

   public boolean compareAndSet (  final long current ,                                  final long next ) {     if ( value.compareAndSet (  current ,                                 next ) )      {         return true;      }     else      {         LockSupport.parkNanos ( 1L );         return false;     } }

   public void set ( final long l )  {     value.set ( l );  }

}

class DataItem{// 数据项 /**    * 而compoundKey为(股东代码,股票代码,持仓类型,flag)的复合体,股东代码占用最63~27位(5位字符和四个字节无符号整数),  * 股票代码占26~11位(两个字节),持仓类型占用10~6位(五个字节),isTail占用第5位,表示是否为尾部,  * 即后继元素中没有相同hash值的元素。 doWrite占用第4位,表示该key正在更改/写入,   * readerCount占用3~0为表示该key正在读的线程数量。     */   /**    * 每条持仓记录,由三个信息来定位(key): 持仓类型(一位字符,A~F), 股东代码(10位字符,第1位A~Z,后面9位是数字0~9),     * 股票代号(short类型)     *     * 被定位到的持仓记录是一个64bit的值(value)    */   private BackOffAtomicLong   compoundKey = new BackOffAtomicLong ( );   // 数据项的关键字    private BackOffAtomicLong   value       = new BackOffAtomicLong ( );;// 存储的值

   public DataItem ( Long key , Long value ) {     this.compoundKey.set ( key );     this.value.set ( value ); }

   public Long getKey ( )    {     return compoundKey.get ( );   }

   public BackOffAtomicLong getBackOffAtomicLongKey ( )  {     return compoundKey;   }

   public boolean setKey ( Long key )    {     return this.compoundKey.compareAndSet ( this.compoundKey.get ( ) ,                                                key );    }

   public Long getValue ( )  {     return value.get ( ); }

   public BackOffAtomicLong getBackOffAtomicLongValue ( )    {     return value; }

   public boolean setValue ( Long value )    {     return this.value.compareAndSet (   this.value.get ( ) ,                                          value );  }

   public boolean equals ( DataItem di ) {     if ( this.getKey ( ) == di.getKey ( ) && this.getValue ( ) == di.getValue ( ) )           return true;      else          return false; }

}

class DataItemUtils{// 用来处理DataItem元素 ,由于看不懂文章里的维护策略,暂时没有使用。

 /**    * tail位为0时表示不是尾,为1时表示是尾    *     * @return 是否是最后一个元素  */   public static boolean isTail ( DataItem i )   {

       return ( ( i.getKey ( ) ) & ( 12L ) ) == 12L;   }

   public static boolean setIsTail ( DataItem i )    {     return i.setKey ( i.getKey ( ) | 12L );   }

   public static boolean setIsNotTail ( DataItem i ) {     return i.setKey ( i.getKey ( ) & 9223372036854775791L );  }

   /**    * 0 未写入 1正在写入     *     * @param i   * @return    */   public static boolean isWrite ( DataItem i )  {     return ( ( i.getKey ( ) ) & ( 8L ) ) == 8L; }

   public static boolean setIsWrite ( DataItem i )   {     return i.setKey ( i.getKey ( ) | 8L );    }

   public static boolean setIsNotWrite ( DataItem i )    {     return i.setKey ( i.getKey ( ) & 9223372036854775799L );  }

   /**    * 是否有线程在读     */   public static boolean isReading ( DataItem i )    {     return ( ( i.getKey ( ) ) & ( 7L ) ) != 0L;  }

   public boolean incrementReading ( DataItem i )    {     if ( ( ( i.getKey ( ) ) & ( 7L ) ) == 7L )          return true;

        i.getBackOffAtomicLongKey ( ).incrementAndGet ( );        return true;  }

   public boolean subtractReading ( DataItem i ) {     if ( ( ( i.getKey ( ) ) & ( 7L ) ) == 0L )          return true;

        i.getBackOffAtomicLongKey ( ).subtractAndGet ( );     return true;  }}

public class MemoryHashTable{// 数组实现的哈希表,开放地址法之再哈希法  private DataItem[]  hashArray;  // 存数据的数组 private int         arraySize;    private DataItem    nonItem;    // 已删除标志  private int         contstant;  // 二次hash函数因子。

  MemoryHashTable ( int size )  {// 哈希表构造函数       arraySize = findPrimeNumber ( size );        hashArray = new DataItem[arraySize];     nonItem = new DataItem ( -1L , -1L );        contstant = findPrimeNumber ( arraySize / 10 );  }

   public void displayTable ( )// 输出哈希表  {     System.out.print ( "Table: " );     for ( int j = 0 ; j < arraySize ; j++ )     {         if ( hashArray[j] != null )              System.out.print ( hashArray[j].getKey ( ) + " " );            else              System.out.print ( "** " );     }     System.out.println ( "" );  }

   // 哈希函数1  private int hashFunc1 ( long key )    {     return Integer.parseInt ( Long.toString ( key % arraySize ) );    }

   // 哈希函数2,不同于哈希函数1,用于再哈希。   private int hashFunc2 ( long key )    {     // array size must be relatively prime to 5, 4, 3, and 2      return Integer.parseInt ( Long.toString ( contstant - key % contstant ) );    }

   // 哈希表中插入数据 这里的CAS是 Test and Test and Test and set    public void insert (    long key ,long value)     {

       int hashVal = hashFunc1 ( key); // 求关键字的哈希值      int stepSize = hashFunc2 ( key ); // 再探测步长的大小

      while ( hashArray[hashVal] != null && hashArray[hashVal].getKey ( ) != -1 )     {         if ( hashArray[hashVal].getKey ( ) == key)          {             //判断当前对象是我们要操作的对象             hashArray[hashVal].setValue ( value );                return ;          }         else          {             hashVal += stepSize; // 单元被占用,再探测                hashVal %= arraySize;            }     }     //此处存在线程不安全问题,如果两个线程中的hashkey完全相同,同时写这个hashVal位置会怎么样???        hashArray[hashVal] = new DataItem ( key , value );   }

   // 在哈希表中删除    public DataItem delete ( long key )   {     int hashVal = hashFunc1 ( key );     int stepSize = hashFunc2 ( key );

      while ( hashArray[hashVal] != null )     {// 直到一个空单元出现         if ( hashArray[hashVal].getKey ( ) == key )         {             DataItem temp = hashArray[hashVal];              hashArray[hashVal] = nonItem; // 作删除标记               return temp;          }         hashVal += stepSize; // 再探测         hashVal %= arraySize;        }     return null;  }

   // 在哈希表中搜索    public long find ( long key ) {     int hashVal = hashFunc1 ( key );     int stepSize = hashFunc2 ( key );

      while ( hashArray[hashVal] != null )     {         if ( hashArray[hashVal].getKey ( ) == key )             return hashArray[hashVal].getValue ( );           hashVal += stepSize;            hashVal %= arraySize;        }     return 0L;    }

   /**    * 找出大于capacity 的最小质数,并且该质数容量是minseed的7分之10 hashtable的装载率不能大于70%    * 用开放地址探测的散列,要保证在一定步数内找到一个空位, 你必须让数组长度为一个质数。在装载率为70%的情况下,    * 一个质数长度的数组,基本就是几步之内你就一定能找到一个空位。   *     * @param capacity    *            hashtable的容量。    *     * @return    */   private Integer findPrimeNumber ( int capacity )  {     capacity = capacity * 10 / 7; // 预计装载量是hashtable容量的70%       if ( capacity % 2 == 0 )        {         // 质数肯定是奇数            capacity++ ;        }     if ( capacity <= 1 )      {         return 2;     }     if ( capacity == 2 || capacity == 3 )     {         return 5;     }     while ( true )        {         int sqrt = (int) Math.sqrt ( capacity );

           for ( int i = 3 ; i <= sqrt ; i += 2 )         {             if ( capacity % i == 0 )                {                 capacity += 2;                  break;                }

           }         return capacity;      } }

}

史上最强算法论战:请不要嘻哈,这是哈希 文章中算法的java实现相关推荐

  1. 史上最强3DGALGAME らぶデス 3 Realtime Lovers 3 海茶3 简介

    接天使哥哥的委托(斑竹) 给大家介绍史上最强3D GALGAME らぶデス 3 性感海茶 3( 这个骇人听闻的标题是百度上的,不是 史上最强的也请不要说我小白 ) 资料汉化人员 策划:天使哥哥(bea ...

  2. 史上最强算法论战:请不要嘻哈,这是哈希

    .这是"美丽互联"微信群里的一次算法论战,感谢书记员硅谷寒(梁寒)精彩的说书般的整理.硅谷寒是"湾区评论(valleytalk)"和36氪的专栏作者. 文章很长 ...

  3. 【CV中的注意力机制】史上最强ResNet变体--ResNeSt

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! [前言]:我们前面已经详细介绍了Attention机制和视觉注意力机制在图像分类结 ...

  4. 【经典干货】GitHub标星10万+,史上最强Google面试指南!

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 一位从1997年就入行的Web工程师,立志要成为Google软件工程师,3年前写下 ...

  5. 3分钟入门python_3分钟学完Python,直接从入门到精通「史上最强干货库」

    作为帅气小编,我已经把python一些模块的甩在这儿了qwq,只要你拿到这些干货,包你玩转python,直接冲向"大佬"的段位,如果已经学了C或者C++或者说如果你需要你的一段关键 ...

  6. 刚刚,史上最强Apollo3.5在CES发布!暗藏百度无人驾驶7大黑科技武器

    雷刚 发自 凹非寺  量子位 报道 | 公众号 QbitAI Wow,wow,wow~ 2019CES大展已开幕,1月8日的Westgate酒店宴会厅现场,感叹声此起彼伏. 这是在百度Apollo C ...

  7. 史上最强Vue,面试、项目全靠它

    史上最强Vue,面试.项目全靠它 vue框架篇 vue的优点 数据驱动的理解 MVVM的理解 组件化的理解 1.组件定义 2.组件的使用场景 3.如何使用组件 4.vue组件产生的过程 数据闪烁 请详 ...

  8. JVM面试题(史上最强、持续更新、吐血推荐)

    JVM面试题(史上最强.持续更新.吐血推荐) 文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 : <尼恩Java面试宝典& ...

  9. 一文深入了解史上最强的Java堆内缓存框架Caffeine

    它提供了一个近乎最佳的命中率.从性能上秒杀其他一堆进程内缓存框架,Spring5更是为了它放弃了使用多年的GuavaCache 缓存,在我们的日常开发中用的非常多,是我们应对各种性能问题支持高并发的一 ...

最新文章

  1. 一个常用的表单文本框input输入提示
  2. c语言如何回缩一个字符,撑大的胃怎样能瘦回去 被撑大的胃还能缩回去吗
  3. python爬取素材图片代码_基于Python爬取素材网站音频文件
  4. python爬取js动态网页_Python 爬取网页中JavaScript动态添加的内容(一)
  5. 四个变量的图表怎么做_PPT中的图表怎么做才高大上?4步帮你搞定!
  6. android连接SQLite数据库-----增加改查+分页
  7. 原创-WINDOWS SERVER 2008 WEB服务器安装配置
  8. 王者荣耀新英雄官宣:鲁班七号之父鲁班大师 即将上线
  9. [swift 进阶]读书笔记-C2P3_Set、 C2P4_Range
  10. `ifdef、`else、`endif 用法
  11. 解决 tesserocr 无法安装问题!
  12. Java虚拟机(JVM)学习合集
  13. 中国线上驾驶游戏市场深度研究分析报告
  14. 这几行最简单的代码 ,却改变了世界
  15. 介绍一个“王者”算法,它能认出游戏里的所有英雄
  16. 掉线(自创--根据刘德华《今天》歌词改编)
  17. JavaEE1(4/23)
  18. android电视识别多区u盘,【当贝市场】电视无法识别U盘APK文件终极方法
  19. 消防法及相关法律法规(二)
  20. 新数据整合的五大方式

热门文章

  1. C#练习题答案: 巴路士惠勒改造【难度:4级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战
  2. OSRAM欧司朗LED灯珠采购秘籍,收藏这一篇就够了
  3. Swift中由找不到removeAll(where:)方法引起的连锁反应(下)
  4. Android中layout目录的作用,Android 开发中layout下的子文件夹
  5. 严冬欲御寒增强体质 首当养肾
  6. 毫秒转换为天、小时、分、秒
  7. 火爆国外的生食饮食法,不允许你不知道
  8. 共享池 shared pool
  9. python进程池win出错,python进程池multiprocessing.Pool运行错误:
  10. abbyy是什么软件