可能重复:
for循环中的最后一个计数器?
下面是我当前正在运行的代码。我希望能够将迭代器I传递到新的Runnable((代码中。我知道我通常需要将变量设为final才能传递到内部类,但这会破坏迭代器的效果。我知道通常我可以尝试让Runnable内部类成为一个真正的类(原谅我缺乏术语(,但那样我就会失去CountDownLatches的效果。
private long generateThreads(int cores){
if (cores <= 0)
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Using " + cores + " threads for processing");
final ExecutorService exec = Executors.newFixedThreadPool(cores);
final CountDownLatch ready = new CountDownLatch(cores);
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch done = new CountDownLatch(cores);
for (int i = 1; i <= cores; i++){
exec.execute(new Runnable(){
public void run(){
ready.countDown();
try{
start.await();
//do work
}
} catch (InterruptedException e){
Thread.currentThread().interrupt();
} finally{
done.countDown();
exec.shutdown();
}
}
});
}
long startTime = 0;
try{
ready.await();
startTime = System.nanoTime();
start.countDown();
done.await();
} catch (InterruptedException e){
e.printStackTrace();
}
return System.nanoTime() - startTime;
}
有人知道给每个线程提供迭代器的方法吗,或者创建一个显示所有外部类成员的类,特别是CountDownLatches吗?
只需将i
的值赋给循环中的最终变量。
for (int i = 1; i <= cores; i++){
final int iFinal = i;
exec.execute(new Runnable(){
public void run(){
ready.countDown();
try{
start.await();
System.out.println( "i=" + iFinal );
} catch (InterruptedException e){
Thread.currentThread().interrupt();
} finally{
done.countDown();
exec.shutdown();
}
}
});
}
如果我理解正确,您希望可运行程序保留对迭代器的"引用",以便它可以观察增量。一种线程安全的方法是使用AtomicInteger
:
final AtomicInteger i = new AtomicInteger(1);
for (; i.get() <= cores; i.incrementAndGet()){
exec.execute(new Runnable(){
public void run(){
//you can access i here
int j = i.get();
}
});
}
注意,这假设您只从Runnables中读取i
——如果您也编写它,条件i.get() <= cores
的行为可能是意外的。
你可以使用这个技巧:
final int[] holder = new int[1]; // the array is final, not its contents
for (int i = 1; i <= cores; i++){
holder[0] = i;
exec.execute(new Runnable(){
public void run(){
int i = holder[0]; // compiles
ready.countDown();
try{
start.await();
//do work
}
} catch (InterruptedException e){
Thread.currentThread().interrupt();
} finally{
done.countDown();
exec.shutdown();
}
}
});
}
编译的原因是数组引用是final
,但数组的内容可以更改。
我不确定这会有多有用,因为尽管我没有彻底阅读你的代码,但它似乎并不线程安全——线程的执行顺序是不确定的,所以当Runnable实际执行时,你的迭代值可能是任何值。
这与您的问题不符,但另一种解决方案是使用Java的一些函数式编程库。我讨厌写线程,这些库可以让你简单地写出你试图用高阶逻辑解决的问题,并在幕后处理并发优化。
Guava和lambdaJ很容易使用。