代码之家  ›  专栏  ›  技术社区  ›  arsenal Rivasa

每个线程使用唯一的ID并将其释放以供重用

  •  1
  • arsenal Rivasa  · 技术社区  · 14 年前

    以下是在 run method ,我一直在努力 unique id from the availableExistingIds releasing 同时通过制作 linked list order ,但在某些情况下,我发现 NoSuchElementException id是 zero few times 我认为这种情况在任何时候都不应该发生。

    class IdPool {
        private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
    
        public IdPool() {
            for (int i = 1; i <= 1000; i++) {
                availableExistingIds.add(i);
            }
        }
    
        public synchronized Integer getExistingId() {
            return availableExistingIds.removeFirst();
        }
    
        public synchronized void releaseExistingId(Integer id) {
            availableExistingIds.add(id);
        }
    }
    
    
    class ThreadNewTask implements Runnable {
        private IdPool idPool;
        private int id;
    
        public ThreadNewTask(IdPool idPool) {
            this.idPool = idPool;
        }
    
        public void run() {
            try {
                id = idPool.getExistingId();
                //Anything wrong here?  
                        if(id==0) {
                            System.out.println("Found Zero");
                        }
                someMethod(id);
            } catch (Exception e) {
                System.out.println(e);
            } finally {
                idPool.releaseExistingId(id);
            }
        }
    
        // This method needs to be synchronized or not?
                private synchronized void someMethod(Integer id) {
                    System.out.println("Task: " +id);
                    // and do other calcuations whatever you need to do in your program
                }
    }
    

    问题说明:-

    我该如何避免这种情况 zero id case 在我的代码里?我可以得到id=0的一种情况是当id池用完(空)时。当这种情况发生时,行:

    id = idPool.getExistingId();
    

    将以失败 无SuchElementException 在这种情况下,finally块将运行:

    idPool.releaseExistingId(id);
    

    但id仍然有它的 default value of 0 因为第一行出现故障。所以我最终“释放”了 0 并将其添加回id池,即使它一开始从未在池中。然后以后的任务可以合法地占用0。这就是我不需要的。有人能建议我如何在代码中克服这种情况吗?我一直希望id应该在 1 to 1000

    1 回复  |  直到 14 年前
        1
  •  5
  •   Mario F    14 年前

    为什么你不修改你的代码,这样当没有可用的id时,它就不会崩溃,而是等待一个可用的id?

    否则,每次有太多线程同时工作时,池就会耗尽,您将不得不处理大量失败的线程。同步工作也会自动为您处理。

    编辑:这是修改后的代码

    class ThreadNewTask implements Runnable {
      private BlockingQueue<Integer> pool;
      private int id;
    
      public ThreadNewTask(BlockingQueue<Integer> pool) {
        this.pool = pool;
      }
    
      public void run() {
        try {
            id = pool.take();
            someMethod(id);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            pool.offer(id);
        }
      }
    
      private void someMethod(Integer id) {
        System.out.println("Task: " +id);
                // and do other calcuations whatever you need to do in your program
      }
    }  
    

    然后,您使用以下内容初始化池:

    LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
    for (int i = 1; i <= 1000; i++) {
      availableExistingIds.add(i);
    }
    BlockingQueue<Integer> pool = new ArrayBlockingQueue<Integer>(1000, false, availableExistingIds);