2016-11-18 13 views
3

В a simple test case я реализовал объединенный сервер потоков на прием до 10 одновременных входящих соединений TLS-PSK на порту 12345 и печать расшифрованы данные на стандартный вывод:Как переназначить объекты для пула с пулом?

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 и MockPSKTlsServer объекты, используемые Runnable?

I.e. как создать 10 из обоих объектов в main(), а затем просто повторно использовать их в run()?

+1

какая версия Java вы используете? –

+0

Я использую [Java SE 1.8] (https://github.com/afarber/jetty-newbie/blob/master/TlsPskServer2/pom.xml) в Windows и Linux –

ответ

3

в вашем случае я хотел бы использовать ThreadLocal для каждого класса (SecureRandom и MockPSKTlsServer), чтобы иметь один выделенный экземпляр SecureRandom и MockPSKTlsServer для каждого потока вашего пула соединений и использовать их, когда нити должен выполнить тот же тип задачи, но с другим входом 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); 
    } 
} 

NB: Используйте try-with-resources заявление автоматически закрыть ввода/вывода потоков.

+0

Если я сделаю переменные 'random' и' server' ** static ** в [MyRunnable.java] (https://github.com/afarber/jetty-newbie/tree/master/TlsPskServer2/src/main/java/de/afarber/tlspskserver2) и имеют 10 экземпляров этого класса - не будут ли они использоваться всеми 10 экземплярами? Мне любопытно, почему вы предлагаете ** static ** здесь? Потому что мне нужно 10 заранее выделенных экземпляров 'SecureRandom' и' MockPSKTlsServer' для каждого потока в моем пуле ... –

+1

Нет, это должно быть ** static **, иначе ваш 'ThreadLocal' был бы бесполезен.Вы должны прочитать javadoc о «ThreadLocal», в двух словах «ThreadLocal» используется для охвата экземпляра данного класса в «Thread», другими словами, какой поток 1 будет получен из «ThreadLocal», будет отличаться из какой нитки 2 получится. Поэтому, если у вас есть 10 потоков, вызывающих 'get()' в 'ThreadLocal',' ThreadLocal' фактически будет управлять 10 экземплярами вашего класса (по одному на поток). –

2

Обычно я использовал бы ThreadLocal<> и использовал легкий класс Pool<T> для хранения и предоставления экземпляров.

Я не думаю, что есть Pool<T> из коробки, но это тривиально построено.

Единственное соображение с ThreadLocal<> - вы должны убедиться, что правильно отпустили обратно до Pool<>. Поэтому, если вы думаете об обмене этого с другим потоком, лучшим подходом может быть статический пул, который является общим, но с блокировкой (если вы не слишком заботитесь о производительности) или параллельным контейнером, если вы это сделаете.

Сказав, что: http://commons.apache.org/proper/commons-pool/

+0

На самом деле я не общаюсь с другими темами. Я читаю входящие данные, расшифровываю их и закрываю сокет. В долгосрочной перспективе я хотел бы переслать дешифрованные данные во встроенный Jetty (который не может [TLS PSK] (https://en.wikipedia.org/wiki/TLS-PSK)) через другой сокет. То есть Я пытаюсь запрограммировать «обратный прокси» с потоком для Jetty. –

+0

Ну, тогда вам не нужен пул, похоже, вам нужен только один экземпляр - в этом случае - игнорировать материал о пуле и вставлять его прямо в 'ThreadLocal <>'. – Nim

+0

Мне кажется, мне нужен пул - для нескольких входящих соединений ... –