java - 具有唯一 ID 的 ArrayBlockingQueue

标签 java multithreading synchronization thread-safety blockingqueue

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

问题陈述:-

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

两种情况:-

  1. 如果command.getDataCriteria()包含Previous,则每个线程 总是需要在1到1000之间使用UNIQUE ID并释放它以供重用 再次。
  2. 否则,如果 command.getDataCriteria() 包含 New,则每个线程 始终需要在2000和3000之间使用UNIQUE ID并将其释放 再次重复使用。

问题:-

我刚刚注意到的一件奇怪的事情是 - 在下面的 else if 循环中,如果您在 run 方法中看到我的下面的代码,如果 command.getDataCriteria() 是 Previous 那么它也会输入else if block (用于 New) 在我进行 .equals 检查时不应该发生?为什么会发生这种情况?

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循环中,如果命令是上一个,那么它也会被输入到else if block 中,这应该是不会发生吧?为什么会发生这种情况?我不知道为什么会发生这种事?

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

最佳答案

如果输入 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 个数字。

关于java - 具有唯一 ID 的 ArrayBlockingQueue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12022310/

相关文章:

java - 简单队列和多线程

ruby - 线程和队列

java - java中的对象同步

java - Servlet 过滤器 - 上下文初始化

java - 跨子域的JSESSIONID

java - Io异常: Connection refused(DESCRIPTION=(TMP=)(VSNNUM=168821248)(ERR=12505)(ERROR_STACK=(ERROR=(CODE=12505)(EMFI=4)))) error

java - 无法解析 JSON : No JsonObject

python - python 是否可以每 1us 激活一个线程?

javascript - Angular数据同步问题

java - swing:有没有办法改变复选框/单选按钮的颜色?