【问题标题】:Conditional delayed processing有条件的延迟处理
【发布时间】:2015-06-15 16:47:32
【问题描述】:

我在 glassfish 下创建了一个新的线程池和一个新的关联监听器。线程池的最大容量为 100 个线程。我有一个每天晚上运行的预定作业,它应该触发来自远程客户端的 HTTP GET 请求。请注意,计划的作业不是 HTTP 客户端。然而,它会触发远程 HTTP 客户端发出 HTTP GET 请求。请求数可以超过100。即使请求数超过100,计划作业也应该不间断地运行。下面是伪代码

class ScheduledJob{

    public executeJob(){
    {
        for(i=0; i<=numberOfTasks; i++)
        {
            connectToTheClientsAndAskThemToFireHTTPGetRequests();
        }
    }

}

我想设计解决方案的方式是让 executeJob 方法以非阻塞方式执行。这意味着最初会触发 100 个请求,其余请求会被缓存。收到 200 OK 后,我将限制剩余的请求。请注意,HTTP 请求可能需要几秒钟,因为响应 HTTP GET 是一个 20MB 的二进制文件。这里的问题是是否有任何开箱即用的解决方案(数据结构)来执行我的缓存和触发业务逻辑,或者任何人都可以提出更好的解决方案。

【问题讨论】:

    标签: java multithreading caching data-structures threadpool


    【解决方案1】:

    一种选择是创建一个Runnable,它采用GetTasks 的并发队列(或任何您想要命名的HTTP GET 请求数据的包装器)。 executeJob() 用所有的GetTasks 填充队列,构造一个100 个线程的线程池,并提交100 个共享同一个并发队列的RunnablesRunnables 将轮询队列直到它为空,此时它们终止。

    public class GetTask {}
    
    public class GetTaskExecutor implements Runnable {
       private final ConcurrentLinkedQueue<GetTask> queue;
    
       public GetTaskExecutor(ConcurrentLinkedQueue<GetTask> queue) {
         this.queue = queue;
       }
    
       public void run() {
         GetTask task = null;
         while((task = queue.poll()) != null) {
           // do work
         }
       }
    }
    
    class ScheduledJob{
        public boolean executeJob(){
            ExecutorService service = Executors.newFixedThreadPool(100);
            ConcurrentLinkedQueue<GetTask> queue = new ConcurrentLinkedQueue<>();
            for(i=0; i<=numberOfTasks; i++) {
                queue.offer(new GetTask());
            }
            for(int i = 0; i < 100; i++) {
                service.execute(new GetTaskExecutor(queue));
            }
            return service.awaitTermination(4, TimeUnit.HOURS);
        }
    }
    

    另一种方法是为每个 GetTask 创建一个 GetTaskExecutor 并将它们全部提交到 ExecutorService - 您使用的是固定线程池,因此一次最多可以执行 100 个任务。

    public class GetTaskExecutor implements Runnable {
       private final GetTask task;
    
       public GetTaskExecutor(GetTask task) {
         this.task = task;
       }
    
       public void run() {
         // do work on single task
       }
    }
    
    class ScheduledJob{
        public boolean executeJob(){
            ExecutorService service = Executors.newFixedThreadPool(100);
            for(i=0; i<=numberOfTasks; i++) {
                service.execute(new GetTaskExecutor(new GetTask());
            }
            return service.awaitTermination(4, TimeUnit.HOURS);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      相关资源
      最近更新 更多