问题描述
我有一个Web服务器服务,客户端请求智能卡计算并获得结果。
在服务器正常运行期间可用智能卡号可以减少或增加,例如我可以从阅读器中物理添加或删除智能卡(或许多其他事件......例如异常等) 。
I have a web server service where clients request a smartcard computation and get their result.Available smartcard number can decrease or increase during the server uptime, for example I can add or remove physically the smartcard from the reader (or many other events... like exception and so on).
智能卡计算可能需要一段时间,如果有对Web服务器的并发请求,我必须优化这些作业以使用所有可用的智能卡。
A smartcard computation can take a while, so I have to optimize these jobs to use all available smartcards if there are concurrent requests to the web server.
我认为可以使用智能卡线程池。至少对我而言,不寻常的是,池应该改变其大小,而不是取决于客户端的请求,而只取决于智能卡的可用性。
I thought to work with a smartcard-thread pool. The unusual thing, at least for me, is that the pool should change its size not depending on the client requests but only on the smartcard availability.
我研究过很多例子:
- BlockingQueue :存储请求和停止线程等待要做的事情看起来不错。
- FutureTask :我可以使用此类来让客户等待它的答案,但是哪种类型的服务员应该完成这项任务?
- ThreadPoolExecutor :似乎我需要什么,但有了这个我无法改变池大小此外,每个线程都应链接到一个智能卡插槽。如果我可以更改池大小(在插入智能卡时添加线程并在移除智能卡时删除线程)以及我是否可以为每个线程分配特定智能卡,这可以是一种解决方案。
- BlockingQueue: It looks good to store request and stop thread waiting for something to do.
- FutureTask: I can use this class to let client waits its answer, but which kind of excecutor should do the task?
- ThreadPoolExecutor: Seems what I need, but with this I cannot change the pool size, moreover every thread should be linked to a single smartcard slot. This can be a solution if I could change the pool size (adding a thread when a smartcard is inserted and removing a thread when a smartcard is removed) and if I can assign a specific smartcard to each thread.
这是智能卡控件,每个智能卡有一个SmartcardWrapper,每个智能卡都有自己的插槽号。
This is the smartcard control, I have one SmartcardWrapper per smartcard, every smartcard has its own slot number.
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;
}
}
我试图创建一个线程池,每个线程一个线程智能卡:
I tried to create a thread pool with one thread per smartcard:
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
}
}
}
每个人在同一输入队列中等待某事:
Everyone waiting for something in the same input queue:
BlockingQueue<byte[]> queue=new BlockingQueue<byte[]>();
但是如何将智能卡线程的输出返回给webserver-client?这让我觉得BlockingQueue不是我的解决方案。
But how to return back output from smartcard-thread to the webserver-client? This let me think that BlockingQueue is not my solution.
如何解决这个问题?我应该遵循哪种并发模式?
每个智能卡分配一个线程是正确的还是我可以简单地使用信号量?
How to approach this problem? Which concurrency pattern should I follow?is it correct to assign one thread per smartcard or should I can simply use semaphores?
推荐答案
您的假设:
不对。
您可以动态设置线程池大小。
看看下面 API
public void setMaximumPoolSize(int maximumPoolSize)
public void setCorePoolSize(int corePoolSize)
Core and maximum pool sizes:
A ThreadPoolExecutor
将根据 corePoolSize
和 maximumPoolSize
设置的范围自动调整池大小。
A ThreadPoolExecutor
will automatically adjust the pool size according to the bounds set by corePoolSize
and maximumPoolSize
.
在方法 execute(java.lang.Runnable)
中提交新任务时,少于 corePoolSize
线程正在运行,即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。
When a new task is submitted in method execute(java.lang.Runnable)
, and fewer than corePoolSize
threads are running, a new thread is created to handle the request, even if other worker threads are idle.
如果有超过 corePoolSize
但小于 maximumPoolSize
线程运行,只有队列已满时才会创建新线程。
If there are more than corePoolSize
but less than maximumPoolSize
threads running, a new thread will be created only if the queue is full.
将 maximumPoolSize
设置为基本无界限的值,例如 Integer.MAX_VALUE
,您允许池容纳任意数量的并发任务。但我不建议有那么多线程。请谨慎设置此值。
By setting maximumPoolSize
to an essentially unbounded value such as Integer.MAX_VALUE
, you allow the pool to accommodate an arbitrary number of concurrent tasks. But I would not recommend to have those many number of threads. Set this value with caution.
最典型的核心和最大池大小仅在构造时设置,但也可以使用 setCorePoolSize动态更改(int
)和 setMaximumPoolSize(int)
。
Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize(int
) and setMaximumPoolSize(int)
.
编辑:
为了更好地利用线程池,如果你知道最大卡数为6,你可以使用
For better utilization of thread pool, if you know the maximum number of cards are 6, you can use
ExecutorService executor = Executors.newFixedThreadPool(6);
OR
这篇关于外部共享资源的Java并发模式(智能卡)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!