2016-11-18 62 views
3

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); 
    } 
} 

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

I.e.如何在main()中创建两个对象中的10个,然后在run()中重新使用它们?

+1

你使用哪个版本的Java? –

+0

我使用Windows和Linux –

回答

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语句自动关闭您的输入/输出流。

+0

如果我在[MyRunnable.java](https://github.com/afarber/jetty-newbie/tree/master)中创建'random'和'server'变量** static **/TlsPskServer2/src/main/java/de/afarber/tlspskserver2)并且拥有该类的10个实例 - 它们不会被所有10个实例使用吗?我很好奇为什么你在这里建议** static **?因为我需要为我的池中的每个线程预先分配10个'SecureRandom'和'MockPSKTlsServer'实例... –

+1

不,它必须是**静态**,否则您的'ThreadLocal'将无用。您应该阅读关于'ThreadLocal'的javadoc,简而言之,'ThreadLocal'用于将给定类的实例范围化为'Thread',换句话说,线程1将从'ThreadLocal'获得的内容将会不同从什么线程2会得到。所以如果你有10个线程在'ThreadLocal'上调用'get()','ThreadLocal'实际上会管理你的类的10个实例(每个线程一个)。 –

2

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

我不认为这是一个Pool<T>开箱即用,但这是平凡的构建。

ThreadLocal<>的唯一考虑因素是您必须确保正确释放回Pool<>。所以,如果你认为这传达给另一个线程的,更好的方法可以是共享的静态池,但无论是用锁定(如果你没有太在意性能)或并发的容器,如果你做..

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

+0

[Java SE的1.8(https://github.com/afarber/jetty-newbie/blob/master/TlsPskServer2/pom.xml)其实,我不与其他线程沟通。我读取传入的数据,解密并关闭套接字。从长远来看,我想通过另一个套接字将解密的数据转发到嵌入式Jetty(不能[TLS PSK](https://en.wikipedia.org/wiki/TLS-PSK))。即我正在尝试为Jetty编写一个线程池“反向代理”。 –

+0

那么,你不需要一个游泳池,看起来你只需要一个实例 - 在这种情况下 - 忽略关于游泳池的东西,并将其直接粘贴在一个'ThreadLocal <>'中。 – Nim

+0

我想我需要一个游泳池 - 对于多个传入连接... –