Java 将int迭代器传递给for循环中定义的新Runnable
可能重复: 下面是我当前正在运行的代码。我希望能够将迭代器I传递到新的可运行代码中。我知道我通常需要make变量final才能传递到内部类,但这会破坏迭代器的效果。我知道通常我可以尝试将可运行的内部类变成一个真正的类,但这样我就失去了倒计时的效果Java 将int迭代器传递给for循环中定义的新Runnable,java,multithreading,concurrency,Java,Multithreading,Concurrency,可能重复: 下面是我当前正在运行的代码。我希望能够将迭代器I传递到新的可运行代码中。我知道我通常需要make变量final才能传递到内部类,但这会破坏迭代器的效果。我知道通常我可以尝试将可运行的内部类变成一个真正的类,但这样我就失去了倒计时的效果 private long generateThreads(int cores){ if (cores <= 0) cores = Runtime.getRuntime().availableProcessors();
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;
}
有人知道给每个线程一个迭代器,或者创建一个显示所有外部类成员的类,特别是倒计时锁的方法吗?如果我理解正确,您希望runnable保留对迭代器的引用,以便它可以观察增量。一种线程安全的方法是使用AtomicInteger:
请注意,这假设您只从可运行程序中读取i-如果您也编写它,则条件i.get的行为如果我理解正确,您希望可运行程序保留对迭代器的引用,以便它可以观察增量。一种线程安全的方法是使用AtomicInteger:
请注意,这假设您仅从可运行程序读取i-如果您也写入i,则条件i.get的行为您可以使用以下技巧:
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();
}
}
});
}
编译的原因是数组引用是最终的,但数组的内容可以更改
我不确定这会有多有用,因为尽管我没有彻底阅读您的代码,但它似乎不是线程安全的-线程的执行顺序是不确定的,所以当Runnable实际执行时,您的迭代值可以是任何值。您可以使用以下技巧:
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();
}
}
});
}
编译的原因是数组引用是最终的,但数组的内容可以更改
我不确定这会有多有用,因为尽管我没有彻底阅读您的代码,但它似乎不是线程安全的-线程的执行顺序是不确定的,所以当Runnable实际执行时,您的迭代值可以是任何值。只需将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();
}
}
});
}
只需将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();
}
}
});
}
这与您的问题背道而驰,但另一种解决方案是使用一些Java函数编程库。我讨厌编写线程,这些库让您可以简单地写出您试图用高阶逻辑解决的问题,并在幕后处理并发优化
Guava和lambdaJ很容易使用。这种方法与您的问题背道而驰,但另一种解决方案是使用一些Java函数编程库。我讨厌编写线程,这些库让您可以简单地写出您试图用高阶逻辑解决的问题,并在幕后处理并发优化
番石榴和lambdaJ易于使用。int i=holder[0]螺纹安全吗?我不确定这样做时是否有可见性保证,即使数组是最终的。@assylias它不是线程安全的,但设计IMHO也不是。这个答案确实回答了这个问题。请参见编辑的Answersis int i=保持架[0]线程安全?我不确定这样做时是否有可见性保证,即使数组是最终的。@assylias它不是线程安全的,但设计IMHO也不是。这个答案确实回答了这个问题。见编辑后的回答-我们都因为太复杂而错过了答案。查看Alex的答案:@Bohemian我不知道-他的答案和我们的答案实现了不同的目标-我不确定OP是否希望看到runnable中的计数器更改,或者只是在runnable创建时获得值…@Bohemian看起来你是对的-是的,谢谢。我也对你投了赞成票,但是我选择了另一个,因为我真的只需要在//do work部分的后面将数字作为偏移量,并且使用int比创建一个全新的对象更好。这两种方法都适用于这种情况,但另一种方法需要更少的内存消耗。非常感谢。again@tophersmith116如果这就是你所需要的,那么另一个答案确实更好。哈哈,我们都错过了答案,因为太复杂了。查看Alex的答案:@Bohemian我不知道-他的答案和我们的答案实现了不同的目标-我不确定OP是否希望看到runnable中的计数器更改,或者只是在runnable创建时获得值…@Bohemian看起来你是对的-是的,谢谢。我也对你投了赞成票,但是我选择了另一个,因为我真的只需要在//do work部分的后面将数字作为偏移量,并且使用int比创建一个全新的对象更好。这两种方法都适用于这种情况,但另一种方法需要更少的内存消耗。非常感谢。again@tophersmith116如果这就是你需要的,那么另一个答案确实更好。哇。。。我做了一个总台。非常感谢你。这是
太好了,我觉得自己很傻。哇。。。我做了一个总台。非常感谢你。这太棒了,我觉得自己很愚蠢。