java MD5 并发
Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。
查看MessageDigest源码
public void update(byte[] input) {
engineUpdate(input, 0, input.length);
state = IN_PROGRESS;
}
可以看到这里调用了engineUpdate方法,此方法进行一个更新操作。
然后state属性的状态就被改变了,表明当前计算正在处理过程中。
state默认属性
private int state = INITIAL;
然后需要调用MessageDigest.digest()方法计算哈希值
public byte[] digest() {
/* Resetting is the responsibility of implementors. */
byte[] result = engineDigest();
state = INITIAL;
return result;
}
到这里已经完成了MD5值的计算,state属性恢复初始状态,如果想要重用MessageDigest对象,还需要调用MessageDigest.reset()方法进行重置,以免这次计算数据会对下一次的计算造成影响,从而导致计算结果错误。
而我所遇到的问题就是,在MessageDigest在多线程的环境下,Thread-1的计算还没有完成的情况下,Thread-2又开始使用该MessageDigest对象进行下一次的计算,Thread-2修改了MessageDigest的状态,Thread-1使用被修改过后的MessageDigest进行计算,从而导致了计算结果错误。
解决方案有两个:
1、加锁来共享同一个MessageDigest;
public class MD5 {
private static final byte[] ToHex_ =
{ '0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f'
};
private MessageDigest md5_ = null;
static private MessageDigest Md5_;
static
{
try { Md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
};
public MD5()
{
try { md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
}
/**
*
*/
public static synchronized String Digest(byte[] dataToHash)
{
Md5_.update(dataToHash, 0, dataToHash.length);
return HexStringFromBytes( Md5_.digest() );
}
/**
* Non-threadsafe MD5 digest (hashing) function
*/
public String digest(byte[] dataToHash)
{
md5_.update(dataToHash, 0, dataToHash.length);
return HexStringFromBytes( md5_.digest() );
}
private static String HexStringFromBytes(byte[] b)
{
byte [] hex_bytes = new byte[ b.length * 2 ];
int i,j=0;
for (i=0; i < b.length; i++)
{
hex_bytes[j] = ToHex_[ ( b[i] & 0xF0 ) >> 4 ] ;
hex_bytes[j+1] = ToHex_[ b[i] & 0xF ];
j+=2;
}
return new String( hex_bytes );
}
}
2、每次新创建一个MessageDigest;
class MD5_test {
public final static String MD5(String s) {
char hexDigits[] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
try {
byte [] strTemp = s.getBytes();
MessageDigest mdTemp = MessageDigest.getInstance("MD5" );
mdTemp.update(strTemp);
byte [] md = mdTemp.digest();
int j = md.length;
char str[] = new char [j * 2 ];
int k = 0 ;
for ( int i = 0 ; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf ];
str[k++] = hexDigits[byte0 & 0xf ];
}
return new String(str);
} catch (Exception e) {
return null ;
}
}
public static void main(String[] args) {
// MD5_Test aa = new MD5_Test();
System.out.print(MD5_test.MD5("a" ));
// System.out.print(MD5_test.MD5("%7B%7DAHRCU" ));
}
}
这两种方案都可解决并发问题。
java MD5 并发的更多相关文章
- Java高并发秒杀API之Service层
Java高并发秒杀API之Service层 第1章 秒杀业务接口设计与实现 1.1service层开发之前的说明 开始Service层的编码之前,我们首先需要进行Dao层编码之后的思考:在Dao层我们 ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- Java线程并发:知识点
Java线程并发:知识点 发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用. 逃逸:在对象尚未准备 ...
- 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计 5】让普通变量也享受原子操作
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray
除了提供基本数据类型外,JDK还为我们准备了数组等复合结构.当前可用的原子数组有:AtomicIntegerArray.AtomicLongArray和AtomicReferenceArray,分别表 ...
- 【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference AtomicReference无法解决上述问题的根 ...
- 【实战Java高并发程序设计 1】Java中的指针:Unsafe类
是<实战Java高并发程序设计>第4章的几点. 如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现.现在,就让我 ...
随机推荐
- TCP/IP详解与OSI七层模型
TCP/IP协议 包含了一系列构成互联网基础的网络协议,是Internet的核心协议.基于TCP/IP的参考模型将协议分成四个层次,它们分别是链路层.网络层.传输层和应用层.下图表示TCP/IP模型与 ...
- DNS记录类型名单
原文:http://www.worldlingo.com/ma/enwiki/zh_cn/List_of_DNS_record_types DNS记录类型名单 这 DNS记录类型名单 提供一个方便索引 ...
- selenium+python 移动鼠标方法
from selenium import webdriver from selenium.webdriver.common.keys import Keys import time driver=we ...
- 手淘flexible.js框架使用和源代码讲解
手淘框架是一个用来适配移动端的js框架,下面我们来讲解一下如何使用手淘的这套框架. 其实手淘框架的核心原理就是根据不同的width给网页中html跟节点设置不同的font-size,然后所有的距离大小 ...
- C语言 字符串处理函数 转自 http://blog.chinaunix.net/uid-25885064-id-3175049.html
C字符串处理函数 2012-04-13 18:14:16 分类: C/C++ void *memccpy (void *dest, const void *src, int c, size_t n) ...
- 关系型数据库与Key-value型数据库Mongodb模式设计对比
MongoDb 相比于传统的 SQL 关系型数据库,最大的不同在于它们的模式设计( Schema Design )上的差别,正是由于这一层次的差别衍生出其它各方面的不同. 我们可以简单的认为关系型数据 ...
- http和https(转)
一.HTTP协议 最近看了一些网络通信方面的书籍,研究了一下 HTTP 和 TCP/IP,有了一些新的收获和理解,在这里做个归纳和总结. (1)什么是HTTP协议 HTTP (HyperText Tr ...
- lnmp架构实现动态php
目录 LNMP动态网站php 1.PHP-FastCGI概述 PHP-FPM安装配置 配置PHP与数据库连接 配置PHP新增扩展模块 配置PHP-FPM主要配置 配置PHP-FPM错误日志 1.编译安 ...
- 关于常见的协议BSD,APACHE,MIT,GPL的理解
其实BSD和APACHE和MIT协议类似,基本就是可以为所欲为,但是要尊重原来的作者. GPL协议是一个免费和开源的协议,只要用了GPL协议的类库源码等,也必须适应GPL协议. 意思就是把开源和免费进 ...
- 「小程序JAVA实战」小程序数据缓存API(54)
转自:https://idig8.com/2018/09/22/xiaochengxujavashizhanxiaochengxushujuhuancunapi52/ 刚开始写小程序的时候,用户信息我 ...