ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new
ThreadPoolExecutor.CallerRunsPolicy());
问题陈述是: -
每个帖子在unique ID
之间使用1 and 1000
,程序必须在60 minutes or more
之间运行,在我的run method
中,当我做id as zero
时我几次(if(id==0))
{ {1}}检查并将断点置于该循环下,我不知道为什么?由于availableExistingIds的值介于1和1000之间,因此我不知道这个zero is coming in my id
在哪里?
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
}
}
以下是程序开始的主要类 -
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
IdPool idPool = new IdPool();
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size), 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) {
service.submit(new ThreadNewTask(idPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
更新: -
我想在这里使用ArrayBlockingQueue,这样当没有可用的id时它会等待崩溃,而是等待一个可用。任何人都可以建议我如何在这里使用它?
实施BlockingQueue后的代码更改。
public void run() {
System.err.println(command.getDataCriteria());
if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_PREVIOUS)) {
try {
System.out.println(command.getDataCriteria());
// Getting existing id from the pool
existId = existPool.take();
attributeGetSetMethod(existId);
} catch (Exception e) {
getLogger().log(LogLevel.ERROR, e.getLocalizedMessage());
} finally {
// And releasing that existing ID for re-use
existPool.offer(existId);
}
}
else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
try {
System.out.println(command.getDataCriteria());
// Getting new id from the pool
newId = newPool.take();
attributeGetSetMethod(newId);
} catch (Exception e) {
getLogger().log(LogLevel.ERROR, e.getLocalizedMessage());
} finally {
// And releasing that new ID for re-use
newPool.offer(newId);
}
}
}
我刚才注意到的一个奇怪的事情是 - 如果你在else if loop
中看到我的上述代码run method
,那么command.getDataCriteria() is Previous
中的上述代码也会在else if block(which is for New)
中输入.equals check
我应该做else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
这不应该发生什么?为什么会这样?
{{1}}
答案 0 :(得分:1)
您可以获得id = 0的一种情况(除了由于您不使用同步而导致未定义行为的可能性)是id池耗尽(空)。当发生这种情况时,行:
id = idPool.getExistingId();
将因NoSuchElementException而失败。在这种情况下,finally
块将运行:
idPool.releaseExistingId(id);
但由于第一行失败,id
的默认值仍为0
。所以你最终“释放”0
并将其添加回id池,即使它从未在池中开始。然后,后面的任务可以合法地0
。
但是,这肯定会在catch块中打印你的异常。
答案 1 :(得分:0)
Java提供(自Java 5起)Semaphore,我相信你正在关注counting semaphore。