1

下面是其中的代码run method,我总是试图同时通过制作 a 来获取它unique id from the availableExistingIds,但在某些情况下我发现,我正在获取并且 id 是我认为任何时候都不应该出现的情况。releasinglinked list orderNoSuchElementExceptionzero 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();

将失败并带有NoSuchElementException. 在这种情况下,finally 块将运行:

idPool.releaseExistingId(id);

但是 id 仍然会default value of 0因为第一行失败而得到它。所以我最终“释放”0并将其添加回 id 池,即使它从未在池中开始。然后以后的任务可以合法地取 0。这就是我不需要的。谁能建议我如何在我的代码中克服这种情况?我总是希望 id 应该在1 to 1000.

4

1 回答 1

5

你为什么不修改你的代码,这样当没有可用的 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);
于 2012-08-18T18:00:10.087 回答