具有唯一ID的ArrayBlockingQueue

时间:2012-08-18 21:14:46

标签: java multithreading synchronization thread-safety blockingqueue

在从StackOverflow获得帮助后,我找到了我在下面实现的解决方案。

问题陈述: -

每个线程每次都需要使用UNIQUE ID,并且必须运行60 minutes或更多,因此在60 minutes中,所有ID's都可能会获得完成后我需要再次重用那些ID's。所以我在这里使用ArrayBlockingQueue概念。

两种情景: -

  1. 如果command.getDataCriteria()包含Previous则每个帖子 始终需要在UNIQUE ID之间使用1 and 1000并将其释放以便重复使用 试。
  2. 如果command.getDataCriteria()包含New,那么每个帖子 始终需要在UNIQUE ID之间使用2000 and 3000并将其发布 再次重复使用。
  3. 问题: -

    我刚刚注意到的一个奇怪的事情是 - 在下面的if if循环中如果你在run方法中看到我的下面的代码,如果command.getDataCriteria() is Previous那么它也会输入else if block(which is for New)中的{0}}我正在做.equals check时发生的事吗?为什么会这样?

    else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
    

    以下是我的代码: -

    class ThreadNewTask implements Runnable {
          private Command command;
          private BlockingQueue<Integer> existPool;
          private BlockingQueue<Integer> newPool;
          private int existId;
          private int newId;
    
    
          public ThreadNewTask(Command command, BlockingQueue<Integer> pool1, BlockingQueue<Integer> pool2) {
                this.command = command;
                this.existPool = pool1;
                this.newPool = pool2;
          }
    
          public void run() {
    
                if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_PREVIOUS)) {
                      try {
                            existId = existPool.take();
                            someMethod(existId);
                      } catch (Exception e) {
                            System.out.println(e);
                      } finally {
                            existPool.offer(existId);
                      }
                } else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
                      try {
                            newId = newPool.take();
                            someMethod(newId);
                      } catch (Exception e) {
                            System.out.println(e);
                      } finally {
                            newPool.offer(newId);
                      }
                }
          }
    
          // And this method needs to be synchronized or not?
          private synchronized void someMethod(int i) {
                System.out.println();
                System.out.println("#####################");
                System.out.println("Task ID: " +i);
                System.out.println("#####################");
                System.out.println();
          }
    }
    
    public class TestingPool {
          public static void main(String[] args) throws InterruptedException {
                int size = 10;
                int durationOfRun = 60;
                LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
                LinkedList<Integer> availableNewIds = new LinkedList<Integer>();
                for (int i = 1; i <= 1000; i++) {
                      availableExistingIds.add(i);
                }
                for (int i = 2000; i <= 3000; i++) {
                      availableNewIds.add(i);
                }
                BlockingQueue<Integer> existIdPool = new ArrayBlockingQueue<Integer>(1000, false, availableExistingIds);
                BlockingQueue<Integer> newIdPool = new ArrayBlockingQueue<Integer>(1000, false, availableNewIds);
    
                // create thread pool with given size
                ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy()); 
    
    
                // queue some tasks
                long startTime = System.currentTimeMillis();
                long endTime = startTime + (durationOfRun * 60 * 1000L);
    
                // Running it for 60 minutes
                while(System.currentTimeMillis() <= endTime) {
                      Command nextCommand = getNextCommandToExecute();
                      service.submit(new ThreadNewTask(nextCommand, existIdPool, newIdPool));
                }
    
                // wait for termination        
                service.shutdown();
                service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
          }
    }
    

    更新: -

    我刚注意到的一个奇怪的事情是 - 在下面的else if loop command is Previous如果else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) { 那么它也会被输入到else if if block中,这个块应该不会发生吗?为什么会这样?我不知道为什么会发生这件事?

    {{1}}

1 个答案:

答案 0 :(得分:1)

如果您输入if ()并输入else,则无法进行其他操作。我没有看到你的代码有什么问题,所以我怀疑你误解了你的输出。您是否期望来自Command的其他getNextCommandToExecute()

我只是使用模拟Command运行您的代码,它设置了一个随机dataCriteria并获得了以下输出。我认为它没有错:

Task ID: 2001
Task ID: 1
Task ID: 2002
Task ID: 2003
Task ID: 2
Task ID: 2004
Task ID: 3
Task ID: 2005
...

您是否期待线程的某种特定时间?给定线程竞争条件,产生的第一个Command 必然是您将看到的第一个输出。

以下是您的代码的一般反馈:

  • 我会使用pool.put(...)而不是offer(...)来回false
  • 您可以在构建它们之后填充队列,而不是使用LinkedList加载它们。
  • 您通常应使用ArrayList代替LinkedList
  • 您加载for (int i = 2000; i <= 3000; i++)但需要从2001年到3000年,否则将超过1000个数字。