Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。

查看MessageDigest源码

  1. public void update(byte[] input) {
  2. engineUpdate(input, 0, input.length);
  3. state = IN_PROGRESS;
  4. }

可以看到这里调用了engineUpdate方法,此方法进行一个更新操作。

然后state属性的状态就被改变了,表明当前计算正在处理过程中。

state默认属性

private int state = INITIAL;

然后需要调用MessageDigest.digest()方法计算哈希值

 

  1. public byte[] digest() {
  2. /* Resetting is the responsibility of implementors. */
  3. byte[] result = engineDigest();
  4. state = INITIAL;
  5. return result;
  6. }

到这里已经完成了MD5值的计算,state属性恢复初始状态,如果想要重用MessageDigest对象,还需要调用MessageDigest.reset()方法进行重置,以免这次计算数据会对下一次的计算造成影响,从而导致计算结果错误。

而我所遇到的问题就是,在MessageDigest在多线程的环境下,Thread-1的计算还没有完成的情况下,Thread-2又开始使用该MessageDigest对象进行下一次的计算,Thread-2修改了MessageDigest的状态,Thread-1使用被修改过后的MessageDigest进行计算,从而导致了计算结果错误。

解决方案有两个:

1、加锁来共享同一个MessageDigest;

  1. public class MD5 {
  2. private static final byte[] ToHex_ =
  3. { '0','1','2','3','4','5','6','7',
  4. '8','9','a','b','c','d','e','f'
  5. };
  6. private MessageDigest md5_ = null;
  7. static private MessageDigest Md5_;
  8. static
  9. {
  10. try { Md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
  11. catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
  12. };
  13.  
  14. public MD5()
  15. {
  16. try { md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
  17. catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
  18. }
  19. /**
  20. *
  21. */
  22. public static synchronized String Digest(byte[] dataToHash)
  23. {
  24. Md5_.update(dataToHash, 0, dataToHash.length);
  25. return HexStringFromBytes( Md5_.digest() );
  26. }
  27. /**
  28. * Non-threadsafe MD5 digest (hashing) function
  29. */
  30. public String digest(byte[] dataToHash)
  31. {
  32. md5_.update(dataToHash, 0, dataToHash.length);
  33. return HexStringFromBytes( md5_.digest() );
  34. }
  35. private static String HexStringFromBytes(byte[] b)
  36. {
  37. byte [] hex_bytes = new byte[ b.length * 2 ];
  38. int i,j=0;
  39. for (i=0; i < b.length; i++)
  40. {
  41. hex_bytes[j] = ToHex_[ ( b[i] & 0xF0 ) >> 4 ] ;
  42. hex_bytes[j+1] = ToHex_[ b[i] & 0xF ];
  43. j+=2;
  44. }
  45. return new String( hex_bytes );
  46. }
  47. }

  

2、每次新创建一个MessageDigest;

  1. class MD5_test {
  2. public final static String MD5(String s) {
  3. char hexDigits[] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
  4. 'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
  5. try {
  6. byte [] strTemp = s.getBytes();
  7. MessageDigest mdTemp = MessageDigest.getInstance("MD5" );
  8. mdTemp.update(strTemp);
  9. byte [] md = mdTemp.digest();
  10. int j = md.length;
  11. char str[] = new char [j * 2 ];
  12. int k = 0 ;
  13. for ( int i = 0 ; i < j; i++) {
  14. byte byte0 = md[i];
  15. str[k++] = hexDigits[byte0 >>> 4 & 0xf ];
  16. str[k++] = hexDigits[byte0 & 0xf ];
  17. }
  18. return new String(str);
  19. } catch (Exception e) {
  20. return null ;
  21. }
  22. }
  23.  
  24. public static void main(String[] args) {
  25. // MD5_Test aa = new MD5_Test();
  26. System.out.print(MD5_test.MD5("a" ));
  27. // System.out.print(MD5_test.MD5("%7B%7DAHRCU" ));
  28. }
  29. }

  

这两种方案都可解决并发问题。

 

java MD5 并发的更多相关文章

  1. Java高并发秒杀API之Service层

    Java高并发秒杀API之Service层 第1章 秒杀业务接口设计与实现 1.1service层开发之前的说明 开始Service层的编码之前,我们首先需要进行Dao层编码之后的思考:在Dao层我们 ...

  2. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  3. Java线程并发:知识点

    Java线程并发:知识点   发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用.   逃逸:在对象尚未准备 ...

  4. 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  5. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  6. 【实战Java高并发程序设计 5】让普通变量也享受原子操作

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  7. 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray

    除了提供基本数据类型外,JDK还为我们准备了数组等复合结构.当前可用的原子数组有:AtomicIntegerArray.AtomicLongArray和AtomicReferenceArray,分别表 ...

  8. 【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference AtomicReference无法解决上述问题的根 ...

  9. 【实战Java高并发程序设计 1】Java中的指针:Unsafe类

    是<实战Java高并发程序设计>第4章的几点. 如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现.现在,就让我 ...

随机推荐

  1. postgraphile 基本试用

    我的测试环境使用docker 进行的安装 基本安装 pg 数据库 我使用的是timesacledb 复制集版本,参考https://github.com/timescale/streaming-rep ...

  2. java并发之原子性、可见性、有序性

    链接:https://blog.csdn.net/gongpulin/article/details/51211616

  3. PostgreSQL 9.6 keepalived主从部署

    ## 环境: PostgreSQL版:9.6 角色                     OS                    IPmaster                 CentOS7 ...

  4. mac电脑 pip安装包后 撞到了系统python里面的解决方法

    /usr/local/Cellar/python@2/2.7.14_3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-pack ...

  5. Ubantu 网卡绑定固定IP

    # The primary network interface auto eth0 #iface eth0 inet dhcp iface eth0 inet static address 192.1 ...

  6. java之扫描包里面的class文件

    一.class作为,编译过后的产物,在很多时候,我们需要通过反射去执行class的具体方法.但是扫描class就是一个很大的问题了. 二.所以我这里写了一个简单的class文件扫描方式. 三.主要是利 ...

  7. 条件随机场(CRF)-IIS学习算法

    改进的迭代尺度法(Improved Iterative Scaling),在很多模型求解中用到,比如最大熵.CRFs等,对模型是对数线性模型的似然都适用.这个算法的思想也很简单,通俗的理解就是通过两个 ...

  8. Linux操作系统-基本命令(一)

    熟悉Linux命令基础 Linux系统的终端窗口 字符终端为用户提供了一个标准的命令行接口,在字符终端窗口中,会显示一个Shell提示符,通常为$. 用户可以在提示符后输入带有选项和参数的字符命令,并 ...

  9. 关于在github上 下载源码 clone 非 master 分支的代码

    https://blog.csdn.net/u012302552/article/details/80680497

  10. [代码][deque容器练习]打分案例

    案例要求: //打分案例(sort算法排序)//创建5个选手(姓名.得分),十个评委对五个选手进行打分//得分规则:去除最高分,去除最低分,取出平均分//按得分对5个选手进行排名 源代码: //打分案 ...