天道酬勤,学无止境

池或不池 java 加密服务提供程序(To Pool or not to Pool java crypto service providers)

问题

解决方案

  • MessageDigest => 根据需要经常创建新实例
  • KeyFactory => 使用单个共享实例
  • SecureRandom => 使用 StackObjectPool
  • 密码 => 使用 StackObjectPool

问题

我在编写安全框架时经常会遇到一个难题:“合并还是不合并”

基本上这个问题分为两个“组”:

  1. 第 1 组: SecureRandom因为对nextBytes(...)的调用是同步的,它可能成为 WebApp/多线程应用程序的瓶颈

  2. 第 2 组:加密服务提供商,例如MessageDigestSignatureCipherKeyFactory ……(因为getInstance()的成本?)

你有什么意见 ?

你对这些问题的习惯是什么?

编辑 09/07/2013

我终于花时间自己测试@Qwerky Share课程,我发现结果非常......令人惊讶。

该课程缺乏我主要关注的问题:像 GenericObjectPool 或 StackObjectPool 这样的池。

所以我重新设计了课程以测试所有 4 个替代方案:

  • 具有同步要点的单个共享实例
  • 每个循环内的新实例(我对您可以将摘要创建拉到循环外的情况不感兴趣)gist
  • 通用对象池:要点
  • 堆栈对象池:要点

我不得不将循环次数降低到 100000,因为 1M 在池上花费了太多时间。

我还在每个循环的末尾添加了一个Thread.yield()以使负载具有更好的形状。

结果(累计运行时间):

  • 信息摘要
    • 新实例:420 秒
    • 单个实例:550 秒
    • 堆栈对象池:800 秒
    • 通用对象池:1900 秒
  • 密钥工厂
    • 新实例:400s
    • 单个实例:350 秒
    • 堆栈对象池:2900 秒
    • 通用对象池:3500 秒
  • 安全随机
    • 堆栈对象池:1600 秒
    • 新实例:2300 秒
    • 通用对象池:2300 秒
    • 单个实例:2800 秒
  • 密码
    • 堆栈对象池:2800 秒
    • 通用对象池:3500 秒
    • 单个实例:5100 秒
    • 新实例:8000 秒

结论

对于 MessageDigest 和 KeyFactory,池是性能杀手,甚至比具有同步瓶颈的单个实例更糟糕,而当涉及到 SecureRandom 和 Cipher 时,它们真的很有用

回答1

如果您让 100 个线程访问共享MessageDigest并让它们每个计算 1,000,000 个哈希值,那么在我的机器上,第一个线程在 70,160 毫秒内完成,最后一个线程在 98,748 毫秒内完成。

如果线程每次都创建MessageDigest的新实例,则第一个线程在 43,392 毫秒和最后一个 58,691 毫秒内完成。

编辑:
事实上,在这个例子中,只有两个线程,创建新实例的例子运行得更快。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Share {

  final byte[] bytes = new byte[100];
  final MessageDigest sharedDigest;
  final ExecutorService pool;
  int threads = 100;

  Share() throws NoSuchAlgorithmException {
    sharedDigest = MessageDigest.getInstance("MD5");
    pool = Executors.newFixedThreadPool(threads);
  }

  void go() {

    for (int i=0; i<threads; i++) {
      pool.execute(new Runnable() {
        public void run() {
          long start = System.currentTimeMillis();
          for (int i=0; i<1000000; i++) {
            /*
            synchronized (sharedDigest) {
              sharedDigest.reset();
              sharedDigest.update(bytes);
              sharedDigest.digest();
            }*/
            try {
              MessageDigest digest = MessageDigest.getInstance("MD5");
              digest.reset();
              digest.update(bytes);
              digest.digest();
            } catch (Exception ex) {
              ex.printStackTrace();
            }
          }
          long end = System.currentTimeMillis();
          System.out.println(end-start);
          pool.shutdown();
        }
      });
    }

  }

  public static void main(String[] args) throws Exception {
    Share share = new Share();
    share.go();
  }

}
回答2

这个测试似乎有利于缓存

long t0 = System.currentTimeMillis();
byte[] bytes = new byte[100];
MessageDigest md = MessageDigest.getInstance("MD5");
for(int i = 0; i < 1000000; i++) {
    //MessageDigest md = MessageDigest.getInstance("MD5");
    md.reset();
    md.update(bytes);
    md.digest();
}
System.out.println(System.currentTimeMillis() - t0);

当 md 在循环外时,它打印 579,在循环内时打印 953。

标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 是否可以以编程方式在 IIS 中启动/停止应用程序池或网站?(Is it possible to start / stop an application pool or website in IIS programatically?)
    问题 我正在尝试找到一种方法来停止、启动、重新启动/回收网站和应用程序池从同一服务器上的 Web 界面内。 理想情况下,这将是我可以用 .NET 做的事情,而不必执行 shell 命令。 (我看到有人问了其他相关问题,但除非有必要,否则我不想从命令行执行此操作)。 我需要能够为 IIS6 和 IIS7 执行此操作。 回答1 您正在寻找 Microsoft.Web.Administration.ServerManager 类。 您可以在此处找到一些入门代码:http://learn.iis.net/page.aspx/226/microsoftwebadministration/。 您可以进一步探索该代码以执行您想要的操作。 我相信整个 appcmd 都是在这个框架之上编写的。 此框架不适用于 IIS6 及以下版本。 你需要 IIS7。 对于 II6,您可以使用 Mehmet Aras 建议的 WMI 方法。 不幸的是,你需要这两个库; 或者也许有一些代码可以抽象这些库。 回答2 您可以使用 WMI(Windows 管理规范)。 在 msdn 上查看使用 WMI 配置 IIS。您还可以访问 WMI 提供程序并与它们交互,包括来自 C# 代码的 IIS。 System.Management 命名空间是一个起点。 我要提醒您的一件事是确定 .NET 中的 WMI 代码是否需要完全信任
  • 部署应用程序时如何避免安装“无限强度” JCE策略文件?(How to avoid installing “Unlimited Strength” JCE policy files when deploying an application?)
    问题 我有一个使用256位AES加密的应用程序,Java开箱即用不支持。 我知道要使此功能正常运行,我在security文件夹中安装了JCE不限强度的jars。 作为开发人员,这很好,我可以安装它们。 我的问题是,由于将分发此应用程序,因此最终用户很可能不会安装这些策略文件。 让最终用户下载这些文件只是为了使该应用程序功能并不是一个有吸引力的解决方案。 有没有一种方法可以使我的应用程序运行而不会覆盖最终用户计算机上的文件? 可以在不安装策略文件的情况下处理它的第三方软件? 还是仅从JAR内引用这些策略文件的方法? 回答1 有两个通常引用的解决方案。 不幸的是,这些都不是完全令人满意的: 安装无限强度策略文件。 尽管这可能是适合您的开发工作站的解决方案,但让非技术用户在每台计算机上安装文件很快成为一个主要麻烦(如果不是障碍)。 无法通过程序分发文件。 它们必须安装在JRE目录中(由于权限的缘故,它甚至可能是只读的)。 跳过JCE API ,使用另一个加密库,例如Bouncy Castle。 这种方法需要一个额外的1MB库,根据应用程序的不同,这可能是一个很大的负担。 复制标准库中包含的功能也很愚蠢。 显然,该API也与通常的JCE接口完全不同。 (BC确实实现了JCE提供程序,但这无济于事,因为在移交给实现之前已应用了密钥强度限制。)该解决方案也不允许您使用256位TLS(SSL
  • Android数据库加密(Android database encryption)
    问题 Android使用SQLite数据库存储数据,我需要对SQLite数据库进行加密,该怎么做? 我了解应用程序数据是私有的。 但是,我需要明确加密我的应用程序正在使用的SQLite数据库。 回答1 SQLCipher是一个SQLite扩展,它提供数据库文件的透明256位AES加密。 较早的sqlcipher(适用于SQLite的开源完整数据库加密)不适用于android。 但现在它可以作为适用于Android平台的Alpha版本发布。 开发人员已更新标准的Android应用程序“ Notepadbot”以使用SQLCipher。 因此,到目前为止,这绝对是最好和最简单的选择。 回答2 数据库经过加密,以防止发生INDIRECT ATTACKS 。 本术语和类: KeyManager.java和Crypto.java摘自Sheran Gunasekera的书Android Apps Security。 我推荐所有这本书阅读。 INDIRECT ATTACKS之所以如此命名,是因为该病毒不会直接INDIRECT ATTACKS您的应用程序。 相反,它遵循的是Android OS。 目的是复制所有SQLite数据库,以期病毒作者可以复制存储在其中的任何敏感信息。 但是,如果您添加了另一层保护,那么病毒作者将看到的只是乱码数据。 让我们建立一个可以在所有应用程序中重用的密码库。
  • 如何在JDBC中建立连接池?(How to establish a connection pool in JDBC?)
    问题 有人可以提供有关如何建立JDBC连接池的示例或链接吗? 通过搜索谷歌,我看到了许多不同的方法来做到这一点,这很令人困惑。 最终,我需要代码来返回java.sql.Connection对象,但是我在入门时遇到了麻烦。欢迎任何建议。 更新: javax.sql或java.sql是否没有池化连接实现? 为什么不最好使用这些? 回答1 如果您需要一个独立的连接池,那么我首选的是C3P0而不是DBCP(我在前面的答案中已经提到过),在高负载下我对DBCP的问题太多了。 使用C3P0非常简单。 从文档中: ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" ); cpds.setUser("swaldman"); cpds.setPassword("test-password"); // the settings below are optional -- c3p0 can work with defaults cpds.setMinPoolSize(5); cpds
  • pix实验指南
    PIX实验指南 一、 PIX的基本使用 拓扑图 需求 PIX采用三向外围结构,DMZ区域采用静态IP,inside区域采用DHCP方式获取IP,PIX充当DHCP服务器,Client需要采用PAT方式访问互联网,Client访问内部服务器采用直接路由的方式,192.168.2.80服务器需要对外发布到TCP80端口,并拒绝外部到outside接口的任何ICMP通信,内部inside到DMZ和互联网可以采用ICMP测试联通性。 配置 PIX Version 7.2(1) ! hostname pixfirewall interface Ethernet0 nameif outside//将E0口配置为外口 security-level 0//将E0口安全级别设置为0 ip address 202.100.1.13 255.255.255.0 ! interface Ethernet1 nameif inside//将E1口配置为内口 security-level 100//将E1口安全级别设置为100 ip address 192.168.1.1 255.255.255.0 ! interface Ethernet2 nameif dmz//将E2口配置为DMZ security-level 50//将E2口安全级别设置为50 ip address 192.168.2.1 255
  • NoSuchAlgorithmException:算法HmacSHA1不可用(NoSuchAlgorithmException: Algorithm HmacSHA1 not available)
    问题 看下面的java行: Mac.getInstance("HmacSHA1"); 如果将其放在一个简单的测试程序中,则它可以在服务器上正常运行。 但是,如果我在容器中使用此行,则会得到 java.security.NoSuchAlgorithmException: Algorithm HmacSHA1 not available at javax.crypto.Mac.getInstance(DashoA13*..) 两种情况下都使用相同的JDK安装。 搜寻了一下之后,我通过做两件事设法使其工作: 从$JAVA_HOME/jre/lib/ext将sunjce_provider.jar复制到容器的lib目录。 在我的代码中添加以下行: java.security.Security.addProvider(new com.sun.crypto.provider.SunJCE()); 具体来说,这是我在Apache James邮箱中发生的,但是我很确定这与JVM选项有关。 这是它使用的启动脚本。 尽管我最终使它起作用了,但是该解决方案感觉太黑了,无法成为正确的解决方案。 我将对正在发生的事情以及更“正确”的解决方案进行解释,这将不胜感激。 相关问题:使用Java加密会导致NoSuchAlgorithmException。 但是,在这种情况下,我非常确定应该立即支持HmacSHA1算法
  • Cipher not initialized
    I decided to use generic object pooling to reuse cipher object by following A Generic and Concurrent Object Pool . The different is that the article using Connection, but I'm using Cipher. Eracom Pool<Cipher> pool = new BoundedBlockingPool<Cipher>(5, new CipherPickerValidator(), new CipherPicker("xxxx")); public Key unwrapKey(byte[] tmkByte) throws Exception { Cipher cipher = pool.get(); System.out.println("Cipher :" + cipher); try{ cipher.init(Cipher.DEPT_MODE, mkkey, alSpec); }catch(Exception e) { System.out.println(e); } byte[] de = cipher.doFinal(tmkByte); SecretKey tmk = new SecretKeySpec
  • 并发性能测试程序编写
    一般要测试软件或者库的性能,需要在多线程条件下进行。本文提供一种编写多线程性能测试的模板,方便大家参考和使用。本文以AES加密和解密为例,并指出Cipher的获取在程序中的不同位置会对程序性能造成的影响。程序代码如下:package com.lazycat.secure.aes; import java.nio.charset.Charset;import java.security.NoSuchAlgorithmException;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; import javax.crypto.Cipher;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.SecretKeySpec; public class AESCoder { public static int count = 1000000; public static CountDownLatch latch =new CountDownLatch(count); public static void main
  • Cisco路由器之Easy虚拟专用网(解决出差员工访问公司内网的问题)
    博文大纲:一、在路由器上实现Easy 虚拟专用网需要配置什么?二、配置实例 前言:由于“Virtual Private Network”(请看首字母,就知道是什么咯)是敏\感词汇,所以在博文中使用它的中文名字“虚拟专用网”来代替。 在之前写过了Cisco路由器之IPSec 虚拟专用网;在Cisco的ASA防火墙上实现IPSec虚拟专用网。这两篇博文都是用于实现总公司和分公司之间建立虚拟专用网的,那么还有一种使用很多的情况,就是出差人员想要访问公司内网的资源呢?由于出差人员只是单一的一个客户端,所以和前两篇博文不一样,前两篇博文搭建虚拟专用网,两端设备都是路由器或防火墙,有固定的IP地址,所以呢,并不能实现出差人员访问,这篇博文的目的,就是实现出差人员可以访问公司内网资源的,这个技术被称之为——Easy 虚拟专用网。 一、在路由器上实现Easy 虚拟专用网需要配置什么? 这篇博文将写下如何在路由器上实现Easy 虚拟专用网。如果网关设备是Cisco ASA防火墙,配置可参考:Cisco ASA防火墙之Easy虚拟专用网 1、XAUTH身份验证 在原有的IPSec协议上,并没有用户验证的功能,所以引入了一个RFC的草案——XAUTH。它是一个虚拟专用网网关的增强特性,提供用户名和密码的方式来验证用户身份。由于这个过程是在两个连接建立之间完成的,所以被戏称为“阶段1.5”
  • 使用新的try-with-resources块对SQLException进行事务回滚(Transaction rollback on SQLException using new try-with-resources block)
    问题 我在尝试资源时遇到问题,我只是想确定一下。 如果我需要对异常做出反应并且仍然需要catch块中的资源,可以使用它吗? 给出的示例是这样的: try (java.sql.Connection con = createConnection()) { con.setAutoCommit(false); Statement stm = con.createStatement(); stm.execute(someQuery); // causes SQLException } catch(SQLException ex) { con.rollback(); // do other stuff } 我担心即使在oracle文档中,我仍然注定要在这种情况下最终使用旧的try-catch-finally-“在try-with-resources语句中捕获并最终阻止,任何catch或finally块都在资源之后运行宣布已关闭。” 回答1 根据语言规范,将在执行catch子句之前关闭连接(http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3.2) 。 一种可能的解决方案是嵌套try-with-resources语句: try (java.sql.Connection con =
  • Python后端Web开发常用组件、命令(干货)
    Python后端开发常用组件、命令(干货) 持续更新中…(详情请查看原文链接,博主是大佬~) 1、生成6位数字随机验证码 import random import string def num_code(length=6): """ 生成长度为length的数字随机验证码 :param length: 验证码长度 :return: 验证码 """ return ''.join(random.choice(string.digits) for i in range(0, length)) import string import random num = string.digits nonce = ''.join(random.sample(num,4)) # 随机数 print(nonce) # 5619 s = string.ascii_letters echostr = ''.join(random.sample(s,4)) # 随机字符串 print(echostr) # ZbNn import uuid print(''.join(str(uuid.uuid4()).split('-'))) # 32位 uuid 2、md5加密 import hashlib # md5加密 def md5_encrypt(en_str): """ 使用md5二次加密生成32位的字符串
  • 这个JAX-WS客户端调用线程安全吗?(Is this JAX-WS client call thread safe?)
    问题 由于WS客户端服务和端口的初始化需要花费很多时间,因此我希望在启动时对其进行一次初始化,并重用端口的同一实例。 初始化看起来像这样: private static RequestContext requestContext = null; static { MyService service = new MyService(); MyPort myPort = service.getMyServicePort(); Map<String, Object> requestContextMap = ((BindingProvider) myPort).getRequestContext(); requestContextMap = ((BindingProvider)myPort).getRequestContext(); requestContextMap.put(BindingProvider.USERNAME_PROPERTY, uName); requestContextMap.put(BindingProvider.PASSWORD_PROPERTY, pWord); rc = new RequestContext(); rc.setApplication("test"); rc.setUserId("test"); } 我班上某处的电话: myPort
  • Java SimpleCrypto类,用于加密/解密,在Coldfusion 9和Java(Android)中产生不同的结果(Java SimpleCrypto Class for encryption / decryption producing different results in Coldfusion 9 and Java (Android))
    问题 我正在尝试使用广泛使用的SimpleCrypto Java类在Java(Android)中对字符串进行加密,并在ColdFusion 9中对字符串进行解密(反之亦然)。 我已经将完全相同的SimpleCrypto类导入到ColdFusion中,并这样称呼它: <cfset myKey = "apple"> <cfscript> sc = createObject("java", "SimpleCrypto").init(); encrypted = sc.encrypt(myKey, "john"); </cfscript> <cfdump var="#encrypted#"> 使用密钥“ apple”对字符串“ john”进行加密时,它将在CF中输出:9E90A36325AE4F4F7352D6469A7068A2 当我在Android中使用EXACT SAME类时: String key = "apple"; try { sEncrypted = SimpleCrypto.encrypt(key, "john"); Log.d(TAG, sEncrypted); } catch (Exception e) { e.printStackTrace(); } 日志输出:CBE2ADDBA9882F545DFEC1700E7CD518 不用说,我要疯了,因为这些结果是不同的。
  • 使用ChaCha20加密和解密字符串(Encrypt and decrypt string using ChaCha20)
    问题 我想使用chacha20解密和加密字符串 BouncyCastleProvider正在使用chacha20技术。 所以我把它放在了罐子里。 并尝试了代码,但无法正常工作。 PBE.java public class PBE extends AppCompatActivity { private static final String salt = "A long, but constant phrase that will be used each time as the salt."; private static final int iterations = 2000; private static final int keyLength = 256; private static final SecureRandom random = new SecureRandom(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pbe); try { Security.insertProviderAt(new BouncyCastleProvider(), 1)
  • Java中的网络通信加密(network communication encryption in java)
    问题 我和一个朋友正在开发具有客户端/服务器-体系结构的Java游戏。 它运行良好,但是我遇到了问题。 我们使用TCP套接字在服务器和客户端之间建立网络。 我们的网络协议未加密,只有看管流的人才能阅读。 我们考虑过如何对它应用某种加密技术,以隐藏登录信息并防止人们编写自己的客户端。 但是,基本的事情(例如增加/减少字节)似乎很容易弄清楚。 用于加密游戏(或至少游戏登录信息)的网络通信的常用方法是什么? 用Java编写服务器和客户端后,有没有有用的Java库? 回答1 使用公共密钥加密(例如RSA)并实现类似SSL握手之类的功能,或者当然使用SSL-在这里您可以看到一个示例。 这是一个简化的序列: 服务器将其公共RSA密钥发送给客户端客户端生成对称密钥(例如使用AES) 客户端使用服务器的公共密钥加密对称密钥并将其发送到服务器服务器解密收到的对称密钥 现在,客户端和服务器都有一个密钥,任何人都不知道。 然后使用该密钥加密所有数据。 回答2 SSL (安全套接字层)很受欢迎,可以处理此类问题。 回答3 查看javax.crypto库或bouncyCastle。 两者都提供加密原语,也用于加密。 根据要获得的安全性,可以使用对称或不对称加密。 但是,也要事先考虑密钥管理。 您在哪里存储私钥/共享密钥。 如果是客户端服务器,最好的方法是使用不对称加密(即RSA,椭圆曲线)
  • 为什么创建线程据说很昂贵?(Why is creating a Thread said to be expensive?)
    问题 Java教程说创建线程很昂贵。 但是为什么价格昂贵呢? 当创建Java线程使创建过程变得昂贵时,究竟发生了什么? 我认为该声明是正确的,但我只是对JVM中的线程创建机制感兴趣。 线程生命周期开销。 线程创建和拆除不是免费的。 实际开销因平台而异,但是线程创建会花费时间,从而在请求处理中引入延迟,并且需要JVM和OS进行某些处理活动。 如果请求是频繁且轻量的(如在大多数服务器应用程序中一样),则为每个请求创建一个新线程可能会消耗大量计算资源。 来自Java并发实践布莱恩·格茨(Brian Goetz),蒂姆·皮尔斯(Tim Peierls),约书亚·布洛赫(Joshua Bloch),约瑟夫·鲍比尔(Joseph Bowbeer),大卫·福尔摩斯(David Holmes),道格·里(Doug Lea) 列印ISBN-10:0-321-34960-1 回答1 为什么创建线程据说很昂贵? 因为>> <<昂贵。 Java线程的创建非常昂贵,因为其中涉及大量工作: 必须为线程堆栈分配并初始化一个大的内存块。 需要进行系统调用以在主机OS中创建/注册本机线程。 需要创建,初始化描述符并将其添加到JVM内部数据结构中。 从某种意义上说,只要线程处于活动状态,它就束缚资源,这也是很昂贵的。 例如线程堆栈,从堆栈可访问的任何对象,JVM线程描述符,OS本机线程描述符。
  • 加密配置文件中的密码? [关闭](Encrypt Password in Configuration Files? [closed])
    问题 关闭。 此问题不符合堆栈溢出准则。 它当前不接受答案。 想改善这个问题吗? 更新问题,使它成为Stack Overflow的主题。 3年前关闭。 改善这个问题 我有一个程序可以从配置文件中读取服务器信息,并希望在该配置中对密码进行加密,该密码可以由我的程序读取并解密。 要求: 加密要存储在文件中的纯文本密码解密从我的程序从文件读取的加密密码 关于我将如何执行此操作的任何建议? 我当时在考虑编写自己的算法,但我认为这绝对是不安全的。 回答1 一种简单的方法是在Java中使用基于密码的加密。 这使您可以使用密码来加密和解密文本。 这基本上意味着使用算法"AES/CBC/PKCS5Padding"初始化javax.crypto.Cipher ,并使用"PBKDF2WithHmacSHA512"算法从javax.crypto.SecretKeyFactory获取密钥。 这是一个代码示例(已更新以替换不太安全的基于MD5的变体): import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java
  • java Fork / Join池,ExecutorService和CountDownLatch(java Fork/Join pool, ExecutorService and CountDownLatch)
    问题 我们在Java中使用了三种不同的多线程技术-Fork / Join pool,Executor Service和CountDownLatch 叉子/加入池(http://www.javacodegeeks.com/2011/02/java-forkjoin-parallel-programming.html) Fork / Join框架旨在使分而治之算法易于并行化。 这种类型的算法非常适合可以分为两个或更多相同类型的子问题的问题。 他们使用递归将问题分解为简单的任务,直到这些变得足够简单以至于可以直接解决。 然后将子问题的解决方案合并以给出原始问题的解决方案 ExecutorService是扩展Executor类并表示异步执行的接口。 它为我们提供了管理结束并检测异步任务进度的机制。 invokeAll() :执行给定的任务,并在所有任务完成时返回保存其状态和结果的Future列表。 Future.isDone()对于返回列表的每个元素为true。 CountDownLatch :(http://examples.javacodegeeks.com/core-java/util/concurrent/countdownlatch-concurrent/java-util-concurrent-countdownlatch-example/)
  • 不要在nodejs中阻塞event loop
    文章目录简介event loop和worker poolevent loop和worker pool中的queue阻塞event loopevent loop的时间复杂度Event Loop中不推荐使用的Node.js核心模块partitioning 或者 offloadingV8引擎的限制REDOS正则表达式DOS***JSON DOS***阻塞Worker Pool总结简介我们知道event loop是nodejs中事件处理的基础,event loop中主要运行的初始化和callback事件。除了event loop之外,nodejs中还有Worker Pool用来处理一些耗时的操作,比如I/O操作。nodejs高效运行的秘诀就是使用异步IO从而可以使用少量的线程来处理大量的客户端请求。而同时,因为使用了少量的线程,所以我们在编写nodejs程序的时候,一定要特别小心。event loop和worker pool在nodejs中有两种类型的线程。第一类线程就是Event Loop也可以被称为主线程,第二类就是一个Worker Pool中的n个Workers线程。如果这两种线程执行callback花费了太多的时间,那么我们就可以认为这两个线程被阻塞了。线程阻塞第一方面会影响程序的性能,因为某些线程被阻塞,就会导致系统资源的占用。因为总的资源是有限的
  • Oracle JDK和OpenJDK之间的区别(Differences between Oracle JDK and OpenJDK)
    问题 注意:此问题来自2014年。从Java 11开始,OpenJDK和Oracle JDK正在融合。 Oracle和OpenJDK之间有什么重要区别吗? 例如,垃圾回收和其他JVM参数是否相同? 两者之间的GC工作方式是否有所不同? 回答1 目前,OpenJDK和Oracle JDK均仅由Oracle创建和维护。 OpenJDK和Oracle JDK是通过TCK(Java技术认证套件)的同一Java规范的实现。 大多数JDK供应商都是在OpenJDK之上编写的,它们做了一些调整[主要是替换许可的专有部件/替换为仅在特定OS上可用的更多高性能项目]组件,而又没有破坏TCK兼容性。 许多供应商实施了Java规范并通过了TCK。 例如,IBM J9,Azul Zulu,Azul Zing和Oracle JDK。 几乎每个现有的JDK都派生自OpenJDK。 正如许多人所建议的那样,许可是JDK之间的一种变化。 从JDK 11开始获得长期支持,Oracle JDK / Java SE现在将需要商业许可。 现在,您应该注意要安装的JDK,因为没有订阅的Oracle JDK可能会停止工作。 资源 参考: Java虚拟机列表 回答2 对于Java 7 ,没有什么至关重要的。 OpenJDK项目主要基于Sun捐赠的HotSpot源代码。 此外,OpenJDK被选为Java 7的参考实现