2017-08-10 89 views
0

假设我们有一个JobItem,它有两个字段jobIddbTableName。 我们还有一个执行程序线程池4.带有跳过项目的Java优先级队列首先再处理

最初,执行程序将运行队列中的第一个作业项目。 如果后面的队列头有相同的dbTableName说tableA,我想获得下一个队列项下一个没有相同dbTableName的作业项并首先执行它。

随着第一份工作可能需要很长的时间,我们最终可能已经处理与其他表的多个其他的工作项目,我们再次

处理TABLEA我们要确保对TableA的所有作业是按顺序处理之前。

我有另一个列表,它保持当前正在运行的作业列表。

目前,我看到只有通过迭代队列项目并检查当前正在运行的作业列表才能提供此类功能。

有没有更好的方法来实现这一目标?

谢谢

+0

你可以使用一个FIFO结构,并在您的队列推回作业时,作业已经运行在桌子上使用相同的名称 – Nathan

回答

0

对于每个表,你需要的就业机会单独的输入队列串行执行。执行程序从队列中获取作业并按顺序运行它们。串行执行程序可以通过两种方式实现:作为线程或作为参与者。线程实现更简单,但需要更多内存。 Actor实现需要额外的依赖线程库。在你的情况下,演员图书馆可以简化为https://github.com/rfqu/CodeSamples/blob/master/src/simpleactor/SimpleActor.java

+0

感谢其的想法单独的输入作业队列。使用这种方法将会更容易实现。 – Lucas

0

你可以创建具有队列的线程池和工作线程。

public void execute(Runnable command) { 

     final int key= command.getKey(); 
     //Some code to check if it is runing 
     final int index = key != Integer.MIN_VALUE ? Math.abs(key) % size : 0; 
     workers[index].execute(command); 
    } 

工人代码

private final AtomicBoolean scheduled = new AtomicBoolean(false); 

    private final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(maximumQueueSize); 

    public void execute(Runnable command) { 
     long timeout = 0; 
     TimeUnit timeUnit = TimeUnit.SECONDS; 
     if (command instanceof TimeoutRunnable) { 
      TimeoutRunnable timeoutRunnable = ((TimeoutRunnable) command); 
      timeout = timeoutRunnable.getTimeout(); 
      timeUnit = timeoutRunnable.getTimeUnit(); 
     } 

     boolean offered; 
     try { 
      if (timeout == 0) { 
       offered = workQueue.offer(command); 
      } else { 
       offered = workQueue.offer(command, timeout, timeUnit); 
      } 
     } catch (InterruptedException e) { 
      throw new RejectedExecutionException("Thread is interrupted while offering work"); 
     } 

     if (!offered) { 
      throw new RejectedExecutionException("Worker queue is full!"); 
     } 

     schedule(); 
    } 

    private void schedule() { 
     //if it is already scheduled, we don't need to schedule it again. 
     if (scheduled.get()) { 
      return; 
     } 

     if (!workQueue.isEmpty() && scheduled.compareAndSet(false, true)) { 
      try { 
       executor.execute(this); 
      } catch (RejectedExecutionException e) { 
       scheduled.set(false); 
       throw e; 
      } 
     } 
    } 

    public void run() { 
     try { 
      Runnable r; 
      do { 
       r = workQueue.poll(); 
       if (r != null) { 
        r.run(); 
       } 
      } 
      while (r != null); 
     } finally { 
      scheduled.set(false); 
      schedule(); 
     } 
    }