我有一个Web服务器服务,客户端请求智能卡计算并获取结果。
可用的智能卡号可以在服务器正常运行期间减少或增加,例如,我可以从读取器中实际添加或删除智能卡(或其他许多事件,例如异常等)。

java - 外部共享资源(智能卡)的Java并发模式-LMLPHP

智能卡计算可能需要一段时间,因此,如果有对Web服务器的并发请求,我必须优化这些作业以使用所有可用的智能卡。

我认为可以使用智能卡线程池。至少对我而言,不寻常的事情是,池应该更改其大小,而不是取决于客户端请求,而仅取决于智能卡的可用性。

java - 外部共享资源(智能卡)的Java并发模式-LMLPHP

我研究了许多例子:

  • 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[]>();
    

    但是如何将输出从智能卡线程返回到Web服务器客户端?这让我认为BlockingQueue不是我的解决方案。

    如何解决这个问题?我应该遵循哪种并发模式?
    为每个智能卡分配一个线程是否正确,还是我应该只使用信号量?

    最佳答案

    您的假设:



    是不正确的。

    You can set thread pool size dynamically.

    看看下面的ThreadPoolExecutor API

    public void setMaximumPoolSize(int maximumPoolSize)
    


    public void setCorePoolSize(int corePoolSize)
    


    Core and maximum pool sizes:
    
    ThreadPoolExecutor将根据corePoolSizemaximumPoolSize设置的范围自动调整池的大小。

    当通过execute(java.lang.Runnable)方法提交新任务时,正在运行的线程数少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。

    如果正在运行的corePoolSize线程多但少于maximumPoolSize线程,则仅当队列已满时才创建新线程。

    通过将maximumPoolSize设置为本质上不受限制的值(例如Integer.MAX_VALUE),可以允许池容纳任意数量的并发任务。但是我不建议拥有那么多线程。请谨慎设置该值。

    最典型地,核心和最大池大小仅在构造时设置,但也可以使用setCorePoolSize(intsetMaximumPoolSize(int)动态更改。

    编辑:

    为了更好地利用线程池,如果您知道最大卡数为6,则可以使用
     ExecutorService executor = Executors.newFixedThreadPool(6);
    

    或者

    关于java - 外部共享资源(智能卡)的Java并发模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34138795/

    10-11 04:22