Шаблон параллелизма Java для внешнего общего ресурса (смарт-карты)
У меня есть служба веб-сервера, где клиенты запрашивают вычисление смарт-карты и получают свой результат. Имеется в наличииномер смарт-карты может уменьшаться или увеличиваться например, во время работы сервера я могу добавить или физически удалить смарт-карту из устройства чтения (или многих других событий ... например, исключение и т. д.).
Вычисление смарт-карты может занять некоторое время, поэтому я должен оптимизировать эти задания, чтобы использовать все доступные смарт-карты при наличии одновременных запросов к веб-серверу.
Я думал работать с пулом потоков смарт-карт. Необычная вещь, по крайней мере для меня, состоит в том, что пул должен менять свой размер не в зависимости от запросов клиента, а только от доступности смарт-карты.
Я изучил много примеров:
BlockingQueue: Выглядит хорошо, чтобы сохранить запрос и остановить поток, ожидающий что-то сделать.FutureTaskЯ могу использовать этот класс, чтобы позволить клиенту ждать своего ответа, но какой тип ученика должен выполнить задачу?ThreadPoolExecutor: Кажется, что мне нужно, но с этим я не могу изменить размер пула, более того, каждый поток должен быть связан с одним слотом смарт-карты. Это может быть решением, если я смогу изменить размер пула (добавление потока при вставленной смарт-карте и удаление потока при удалении смарт-карты) и если я могу назначить определенную смарт-карту каждому потоку.Это элемент управления смарт-картой, у меня по одному SmartcardWrapper на каждую смарт-карту, каждая смарт-карта имеет свой номер слота.
public class SmartcardWrapper{
private int slot;
public SmartcardWrapper(int slot) {
this.slot=slot;
}
public byte[] compute(byte[] input) {
byte[] out=new byte[];
SmartcardApi.computerInput(slot,input,out); //Native method
return out;
}
}
Я попытался создать пул потоков с одним потоком на одну смарт-карту:
private class SmartcardThread extends Thread{
protected SmartcardWrapper sw;
public SmartcardThread(SmartcardWrapper sw){
this.sw=sw;
}
@Override
public void run() {
while(true){
byte[] input=queue.take();
byte output=sw.compute(input);
// I have to return back the output to the client
}
}
}
Все ждут чего-то в одной очереди ввода:
BlockingQueue<byte[]> queue=new BlockingQueue<byte[]>();
Но как вернуть обратно вывод из потока смарт-карт в веб-сервер-клиент? Это позволило мне думать, что BlockingQueue не мое решение.
Как подойти к этой проблеме? Какой схеме параллелизма я должен следовать? Правильно ли назначать один поток для каждой смарт-карты или я могу просто использовать семафоры?