gpt4 book ai didi

java - 始终获取唯一 ID 并将其释放以供重复使用

转载 作者:行者123 更新时间:2023-12-01 15:13:15 25 4
gpt4 key购买 nike

ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new
ThreadPoolExecutor.CallerRunsPolicy());

问题陈述是:-

每个线程使用 1 到 1000 之间的唯一 ID,并且程序必须运行 60 分钟或更长时间,在我的运行中方法当我进行(if(id==0))检查时,我几次得到id为零并且我将断点放在该循环下,我不知道为什么?由于 availableExistingIds 的值在 1 到 1000 之间,所以我不知道我的 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时它就不会崩溃,而是等待一个可用的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循环中,如果您在run方法中看到我上面的代码,如果command.getDataCriteria () 是 Previous 然后它也会被输入到 else if block (用于 New) 中,这不应该在我进行 .equals 检查时发生?为什么会发生这种情况?

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

最佳答案

在一种情况下,您可能会得到 id = 0(除了由于不使用同步而导致未定义行为的可能性)是当 id 池耗尽(空)时。当发生这种情况时,该行:

id = idPool.getExistingId();

将失败并出现 NoSuchElementException。在这种情况下,finally block 将运行:

idPool.releaseExistingId(id);

但是由于第一行失败,id 仍将具有默认值 0。因此,您最终“释放”0 并将其添加回 id 池,即使它一开始就不在池中。那么后面的任务就可以合法地获取0

但是,如果发生的话,这肯定会在 catch block 中打印您的异常。

关于java - 始终获取唯一 ID 并将其释放以供重复使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12015742/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com