在 StackOverflow 的帮助下,我找到了下面实现的解决方案。
问题陈述:-
每个线程每次都需要使用UNIQUE ID
,并且必须运行60分钟
或更长时间,因此在这60分钟
中可能所有ID's
都会完成,所以我需要再次重用这些ID's
。所以我在这里使用 ArrayBlockingQueue 概念。
两种情况:-
- 如果
command.getDataCriteria()
包含Previous
,则每个线程 总是需要在1到1000
之间使用UNIQUE ID
并释放它以供重用 再次。 - 否则,如果
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/