我有这段代码:
private ConcurrentLinkedQueue<Interval> intervals = new ConcurrentLinkedQueue();
@Override
public void run(){
while(!intervals.isEmpty()){
//remove one interval
//do calculations
//add some intervals
}
}
此代码同时由特定数量的线程执行。正如您所看到的,循环应该继续直到集合中没有更多的间隔为止,但是有一个问题。在每次迭代的开始处,会从集合中删除一个间隔,并且在结束时可能会将一些间隔重新添加回同一集合中。
问题是,当一个线程在循环内部时,集合可能变为空,因此试图进入循环的其他线程将无法这样做并会过早完成其工作,即使第一个线程完成迭代后集合可能被填充。 我希望线程计数保持不变(或不超过某个数字n)直到所有工作真正完成。
这意味着当前没有线程在循环中工作,并且集合中没有剩余元素。有哪些可能的方法可以实现这一点?欢迎任何想法。
解决此问题的一种方法是在我的特定情况下为每个线程提供原始集合的不同部分。但是,当一个线程完成其工作后,程序将不再使用它,即使它可以帮助其他线程进行计算,因此我不喜欢这种解决方案,因为在我的问题中利用机器的所有内核非常重要。
这是我能想出的最简单的最小工作示例。可能太冗长了。
public class Test{
private ConcurrentLinkedQueue<Interval> intervals = new ConcurrentLinkedQueue();
private int threadNumber;
private Thread[] threads;
private double result;
public Test(int threadNumber){
intervals.add(new Interval(0, 1));
this.threadNumber = threadNumber;
threads = new Thread[threadNumber];
}
public double find(){
for(int i = 0; i < threadNumber; i++){
threads[i] = new Thread(new Finder());
threads[i].start();
}
try{
for(int i = 0; i < threadNumber; i++){
threads[i].join();
}
}
catch(InterruptedException e){
System.err.println(e);
}
return result;
}
private class Finder implements Runnable{
@Override
public void run(){
while(!intervals.isEmpty()){
Interval interval = intervals.poll();
if(interval.high - interval.low > 1e-6){
double middle = (interval.high + interval.low) / 2;
boolean something = true;
if(something){
intervals.add(new Interval(interval.low + 0.1, middle - 0.1));
intervals.add(new Interval(middle + 0.1, interval.high - 0.1));
}
else{
intervals.add(new Interval(interval.low + 0.1, interval.high - 0.1));
}
}
}
}
}
private class Interval{
double low;
double high;
public Interval(double low, double high){
this.low = low;
this.high = high;
}
}
}
您可能需要了解的程序相关信息:在每次迭代后,时间间隔应该要么消失(因为它太小),要么变小,要么分裂成两个更小的间隔。在没有剩余间隔时,工作完成。此外,我应该能够通过某个数字n限制执行此工作的线程数量。实际程序通过将间隔分成几部分并使用一些规则丢弃不能包含最大值的那些部分来查找某些函数的最大值,但这对我的问题并不是真正相关的。