У меня есть служба веб-сервера, где клиенты запрашивают вычисления смарт-карт и получают их результат. Доступный номер смарт-карты может уменьшаться или увеличиваться во время работы сервера, например, я могу добавить или удалить физически смарт-карту от читателя (или многие другие события... например, исключение и т.д.).
Вычисление смарт-карт может занять некоторое время, поэтому мне нужно оптимизировать эти задания, чтобы использовать все доступные смарт-карты, если на веб-сервере есть параллельные запросы.
Я думал работать с пулом смарт-карт. Необычная вещь, по крайней мере для меня, заключается в том, что пул должен менять свой размер не в зависимости от клиентских запросов, а только от наличия смарт-карты.
Я изучил множество примеров:
- BlockingQueue. Хорошо выглядит, чтобы хранить запрос и останавливать поток, ожидая чего-то.
- FutureTask. Я могу использовать этот класс, чтобы клиент ожидал ответа, но какой excecutor должен выполнить эту задачу?
- ThreadPoolExecutor: Мне кажется, что мне нужно, но с этим я не могу изменить размер пула, причем каждый поток должен быть связан с одним слотом для смарт-карт. Это может быть решением, если я могу изменить размер пула (добавив поток при вставленной смарт-карте и удалив поток при удалении смарт-карты), и если я могу назначить конкретную смарт-карту для каждого потока.
Это управление смарт-картами, у меня есть один смарт-карт на смарт-карте, каждая смарт-карта имеет свой собственный номер слота.
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[]>();
Но как вернуть обратный вывод из smartcard-thread на веб-сервер-клиент? Это позволяет мне думать, что BlockingQueue не является моим решением.
Как подойти к этой проблеме? Какую модель concurrency следует придерживаться? правильно ли назначить один поток на смарт-карту или я просто могу использовать семафоры?