Нужен потокобезопасный MessageDigest в Java
Мне нужно хэшировать несколько ключей из нескольких потоков, используя MessageDigest в среде, критичной к производительности. Я узнал, что MessageDigest не является потокобезопасным, поскольку хранит свое состояние в своем объекте. Каков наилучший способ достижения потокового хеширования ключей?
Случай использования:
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
//somewhere later, just need to hash a key, nothing else
messageDigest.update(key);
byte[] bytes = messageDigest.digest();
В частности:
- Будет ли ThreadLocal гарантированно работать? Будет ли снижение производительности?
- Отличаются ли объекты, возвращаемые getInstance, и они не мешают друг другу? В документации написано "новый" объект, но я не уверен, является ли это просто оболочкой для (общего) общего конкретного класса?
- Если getInstance() возвращает "реальные" новые объекты, целесообразно ли создавать новый экземпляр каждый раз, когда мне нужно вычислить хэш? С точки зрения снижения производительности - насколько это дорого?
Мой вариант использования очень прост - просто хешируйте простой ключ. Я не могу позволить себе использовать синхронизацию.
Спасибо,
3 ответа
Создать новыйMessageDigest
экземпляр каждый раз, когда вам нужен.
Все экземпляры вернулись из getInstance()
различны. Они должны быть, так как они поддерживают отдельные дайджесты (и если этого вам недостаточно, вот ссылка на источник).
ThreadLocal
может обеспечить выигрыш в производительности при использовании с пулом потоков для поддержки дорогостоящих объектов. MessageDigest
не особенно дорого построить (опять же, посмотрите на источник).
В качестве альтернативы используйте DigestUtils, поточно- ориентированную оболочку Apache Commons для MessageDigest.
sha1 () делает то, что вам нужно:
byte[] bytes = sha1(key)
Вы могли бы использовать ImmutableMessageDigest
из Caesar, библиотеки с открытым исходным кодом, которую я написал.
По сути, он обертывает MessageDigest
экземпляр и клонирует его перед каждым digest()
или update()
вызов.
DigestUtils, похоже, не более безопасен для потоков, чем необработанный MessageDigest. По-прежнему использует MessageDigest.getInstance под обложками.