[英]Is a static method containing loops thread-safe?
I have a huge loop that I wanted to split up into 4 threads. 我有一个巨大的循环,我想分成4个线程。 I've done so using a little bit noobish method(or maybe not?) and split up the counter of the for loops into 4 intervals, created a new Printwriter, and CrucibleOptimizer for each thread so that there are no conflicts, like this:
我这样做是使用一点笨拙的方法(或者可能不是吗?),并将for循环的计数器分成4个间隔,为每个线程创建一个新的Printwriter和CrucibleOptimizer,这样就不会出现冲突,如下所示:
public static void main(String[] args) {
Runnable run1 = new Runnable() {
@Override
public void run() {
PrintWriter writer1;
try {
writer1 = new PrintWriter("test_result1.txt");
CrucibleOptimizer optimizer1 = new CrucibleOptimizer();
int[] loop1boundries = new int[]{1, 7};
opt(optimizer1, writer1, loop1boundries[0], loop1boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run2 = new Runnable() {
@Override
public void run() {
PrintWriter writer2;
try {
writer2 = new PrintWriter("test_result2.txt");
CrucibleOptimizer optimizer2 = new CrucibleOptimizer();
int[] loop2boundries = new int[]{8, 14};
opt(optimizer2, writer2, loop2boundries[0], loop2boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run3 = new Runnable() {
@Override
public void run() {
PrintWriter writer3;
try {
writer3 = new PrintWriter("test_result3.txt");
CrucibleOptimizer optimizer3 = new CrucibleOptimizer();
int[] loop3boundries = new int[]{15, 22};
opt(optimizer3, writer3, loop3boundries[0], loop3boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run4 = new Runnable() {
@Override
public void run() {
PrintWriter writer4;
try {
writer4 = new PrintWriter("test_result4.txt");
CrucibleOptimizer optimizer4 = new CrucibleOptimizer();
int[] loop4boundries = new int[]{23, 30};
opt(optimizer4, writer4, loop4boundries[0], loop4boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Thread[] threads = new Thread[]{new Thread(run1), new Thread(run2), new Thread(run3), new Thread(run4)};
for (Thread thr : threads){
thr.start();
}
}
And this is the method that I'm asking about. 这就是我要问的方法。 I don't know if its thread safe.
我不知道它的线程是否安全。 I've been reading around and google says that as far as I don't have any local variables, I'm fine, but what concerns me is the multiple counters in those loops:
我一直在阅读,谷歌说,就我没有任何局部变量而言,我很好,但是让我担心的是那些循环中的多个计数器:
public static void opt(CrucibleOptimizer opt, PrintWriter writer, int minIncluded, int maxIncluded){
//more than this is never used
final int oreMaterialsMaximum = 100;//100
final int ingotMaterialMaximum = 30;//30
//test for every possible material combination
for (int a = minIncluded; a <= maxIncluded; a++){//for amount of ingots
System.out.println("Testing for ingot number: " + a);
double ratioMin = (Reference.UNITS_IMPOSSIBLE / (double)(a * Reference.UNITS_INGOT));
for (int i = 0; i <= (int)(100 / Reference.UNITS_IMPOSSIBLE); i++){//for every ratio possible
double currentRatio = round(i * ratioMin, 6);
System.out.println("Testing for ratio: " + currentRatio);
for (int b = 0; b <= ingotMaterialMaximum; b++){//with every amount of ingots
for (int c = 0; c <= oreMaterialsMaximum; c++){//with every amount of rich ore
for (int d = 0; d <= oreMaterialsMaximum; d++){//with every amount of normal ore
for (int e = 0; e <= oreMaterialsMaximum; e++){//with every amount of poor ore
for (int f = 0; f <= oreMaterialsMaximum; f++){//with every amount of small ore
opt.set(null, null, null, a); //only the ingots are passed in this way
int[] res = opt.optimizeMaterial(new int[]{c, d, e, f, b}, currentRatio);
if (res != null){
int units = 0;
for (int j = 0; j < res.length; j++)
units += res[j] * Reference.MATERIAL_UNITS[j];
double unitsRight = Math.round(a * Reference.UNITS_INGOT * currentRatio);
if (units != (int)unitsRight){ //if the units are not correct, log
writer.println("I: " + a + " Rat: " + currentRatio + " I_av: " + b + " O_Ri: " + c + " O_No: " + d +
" O_Po: " + e + " O_Sm: " + f + " units_wrong: " + units + " units_right: " + (int)unitsRight);
}
}
}
}
}
}
}
}
}
System.out.println("Testing done");
writer.close();
}
The "do not use static variables" advise is indeed too simplistic: the other requirement is to not pass shared objects to static
methods running in different threads. “不要使用静态变量”建议确实太简单了:另一个要求是不要将共享对象传递给在不同线程中运行的
static
方法。
Loop counters and other primitive local variables are thread-safe. 循环计数器和其他原始局部变量是线程安全的。 The only thing that could make a method non-thread safe is shared state.
可使方法成为非线程安全的唯一方法是共享状态。 It appears that you have successfully avoided that by creating separate
CrucibleOptimizer
and PrintWriter
objects. 通过创建单独的
CrucibleOptimizer
和PrintWriter
对象,您似乎已成功避免了这种情况。
One refactoring that I would attempt is combining your Runnable
s. 我尝试的一种重构是合并您的
Runnable
。 Make a named class that takes loop boundaries, and make four instances of that class in your main
. 创建一个具有循环边界的命名类,并在
main
中创建该类的四个实例。 This would work better than four separate anonymous classes that have very few differences: 这将比四个几乎没有什么区别的独立匿名类更好:
private static class ThreadRunnable implements Runnable {
final String fileName;
final int[] loopBoundaries;
public ThreadRunnable(String fn, int[] lb) {
fileName = fn;
loopBoundaries = lb;
}
@Override
public void run() {
PrintWriter pw;
try {
pw = new PrintWriter(fileName);
CrucibleOptimizer co = new CrucibleOptimizer();
opt(co, pw, loop4boundries[0], loop4boundries[1]);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Now you can make four ThreadRunnable
instances which share identical code. 现在,您可以制作四个共享相同代码的
ThreadRunnable
实例。
Loops in of themselves are thread safe, so no you don't need to worry about that. 循环本身是线程安全的,所以不,您不必担心。
The only thing you need to worry about is anything that might be accessed by multiple threads at once. 您唯一需要担心的是可能同时被多个线程访问的任何内容。
However your entire architecture really needs some work. 但是,您的整个体系结构确实需要一些工作。
For example why have 4 separate implementations for the runables rather than having one implementation and passing parameters into it to say which chunk to work on. 例如,为什么对可运行对象有4个单独的实现,而不是有一个实现并将参数传递到其中以说出要处理的块,为什么呢?
I also don't know what you are trying to do with all the loops but it's highly unlikely you really need any structure like that. 我也不知道您要对所有循环执行什么操作,但是您真的不太需要这样的结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.