Мне нужно создать пул воркеров на Java, где у каждого воркера есть свой собственный подключенный сокет; когда рабочий поток запускается, он использует сокет, но оставляет его открытым для повторного использования позже. Мы выбрали этот подход, потому что накладные расходы, связанные с созданием, подключением и уничтожением сокетов на специальной основе, требовали слишком много накладных расходов, поэтому нам нужен метод, с помощью которого пул рабочих процессов предварительно инициализируется с их подключением к сокетам, готовым к взять на себя работу, сохраняя при этом ресурсы сокета в безопасности от других потоков (сокеты не являются потокобезопасными), поэтому нам нужно что-то в этом направлении ...
public class SocketTask implements Runnable {
Socket socket;
public SocketTask(){
//create + connect socket here
}
public void run(){
//use socket here
}
}
При запуске приложения мы хотим инициализировать рабочие процессы и, надеюсь, соединения сокетов каким-то образом ...
MyWorkerPool pool = new MyWorkerPool();
for( int i = 0; i < 100; i++)
pool.addWorker( new WorkerThread());
Поскольку приложение запрашивает работу, мы отправляем задачи в рабочий пул для немедленного выполнения ...
pool.queueWork( new SocketTask(..));
Обновлено с помощью рабочего кода
На основании полезных комментариев Грея и jontejj, у меня есть следующий рабочий код ...
SocketTask
public class SocketTask implements Runnable {
private String workDetails;
private static final ThreadLocal<Socket> threadLocal =
new ThreadLocal<Socket>(){
@Override
protected Socket initialValue(){
return new Socket();
}
};
public SocketTask(String details){
this.workDetails = details;
}
public void run(){
Socket s = getSocket(); //gets from threadlocal
//send data on socket based on workDetails, etc.
}
public static Socket getSocket(){
return threadLocal.get();
}
}
ExecutorService
ExecutorService threadPool =
Executors.newFixedThreadPool(5, Executors.defaultThreadFactory());
int tasks = 15;
for( int i = 1; i <= tasks; i++){
threadPool.execute(new SocketTask("foobar-" + i));
}
Мне такой подход нравится по нескольким причинам ...
- Сокеты - это локальные объекты (через ThreadLocal), доступные для запущенных задач, что устраняет проблемы параллелизма.
- Сокеты создаются один раз и остаются открытыми, повторно используются при постановке новых задач в очередь, что устраняет накладные расходы на создание / уничтожение объекта сокета.