如何预先为线程池服务器分配对象?

时间:2016-11-18 12:09:34

标签: java ssl threadpool bouncycastle tls-psk

a simple test case中,我实现了一个线程池服务器,在端口12345接受多达10个同时传入的TLS PSK连接,并以标准输出打印解密数据:

public static void main(String[] args) throws IOException {
    ServerSocket server  = new ServerSocket(12345);
    ExecutorService pool = Executors.newFixedThreadPool(10);

    while (true) {
        Socket socket = server.accept();
        pool.execute(new MyRunnable(socket));
    }
}

以下是线程使用的Runnable实现:

@Override
public void run() {
    try {
        SecureRandom random      = new SecureRandom();       // How to preallocate?
        BufferedInputStream bis  = new BufferedInputStream(mSocket.getInputStream());
        BufferedOutputStream bos = new BufferedOutputStream(mSocket.getOutputStream());
        TlsServerProtocol proto  = new TlsServerProtocol(bis, bos, random);
        MockPSKTlsServer server  = new MockPSKTlsServer();   // How to preallocate?
        proto.accept(server);
        Streams.pipeAll(proto.getInputStream(), System.out);
        proto.close();
    } catch (IOException e) {
        System.err.print(e);
    }
}

如何预分配SecureRandom使用的MockPSKTlsServerRunnable个对象?

即。如何在main()中创建10个对象,然后在run()中重复使用它们?

2 个答案:

答案 0 :(得分:3)

在您的情况下,我会为每个班级SecureRandomMockPSKTlsServer)使用ThreadLocal,以便为SecureRandomMockPSKTlsServer设置一个专用实例连接池的每个线程,当线程必须执行相同类型的任务但具有不同的输入Socket时,重用它们,如:

private static final ThreadLocal<SecureRandom> random = ThreadLocal.withInitial(
    SecureRandom::new
);
private static final ThreadLocal<MockPSKTlsServer> server = ThreadLocal.withInitial(
    MockPSKTlsServer::new
);

...
public void run() {
    try (BufferedInputStream bis  = new BufferedInputStream(mSocket.getInputStream());
        BufferedOutputStream bos = new BufferedOutputStream(mSocket.getOutputStream());
        TlsServerProtocol proto  = new TlsServerProtocol(bis, bos, random.get())) {
        // Calling server.get() will get the instance dedicated to the current
        // thread, if no instance exists so far for this thread
        // new MockPSKTlsServer() will automatically be called then
        // affected to this thread for subsequent get's calls
        proto.accept(server.get());
        ...
    } catch (IOException e) {
        System.err.print(e);
    }
}

注意:使用try-with-resources语句自动关闭输入/输出流。

答案 1 :(得分:2)

通常我会使用ThreadLocal<>并使用轻量级Pool<T>类来保存和提供实例。

我不认为开箱即用Pool<T>,但这很简单。

使用ThreadLocal<>的唯一考虑因素是您必须确保正确地释放回Pool<>。因此,如果您正在考虑将此信息传达给另一个线程,更好的方法可能是共享的静态池,但要么是锁定(如果您不太关心性能),要么是并发容器,如果您这样做..

说完:http://commons.apache.org/proper/commons-pool/