3

一个简单的测试案例中,我实现了一个线程池服务器,在端口 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);
    }
}

如何预分配SecureRandomMockPSKTlsServer使用的对象Runnable

即如何在 中创建两个对象中的 10 个,main()然后在 中重用它们run()

4

2 回答 2

3

在您的情况下,我将为ThreadLocal每个类(SecureRandomMockPSKTlsServer)使用一个专用实例,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语句自动关闭您的输入/输出流。

于 2016-11-18T12:24:40.620 回答
2

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

我不认为有一个Pool<T>开箱即用的,但这是微不足道的。

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

话虽如此:http ://commons.apache.org/proper/commons-pool/

于 2016-11-18T12:23:49.480 回答