Java 具有同步arraylist的并行任务
我的作业是使用并行化创建项目,所有这些都应该是正确的。 然而,我做了我的项目,但我的教授提到我的代码中有一些错误“请看数组列表,有些不正常,可能是同步?” 我想请你们社区帮助我,指出可能的错误。我想不通过Java 具有同步arraylist的并行任务,java,multithreading,arraylist,parallel-processing,synchronized,Java,Multithreading,Arraylist,Parallel Processing,Synchronized,我的作业是使用并行化创建项目,所有这些都应该是正确的。 然而,我做了我的项目,但我的教授提到我的代码中有一些错误“请看数组列表,有些不正常,可能是同步?” 我想请你们社区帮助我,指出可能的错误。我想不通过同步括号覆盖我的数组列表可能会有问题,对吗 import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.u
同步括号覆盖我的数组列表可能会有问题,对吗
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* My project finds all dividors for specific number
*It must use threads, so I made them. First I start them (first loop)
*then join them (second loop). My project must have that loops.
*Problem might be with not synchronizing methods array list...
*/
public class Main {
private final static int NUMBER = 100;
private final static List<Integer> dividors = new ArrayList<Integer>();
public static void main(String[] args) {
new Main().doStuff();
}
private int sqr;
private int sqrp1;
private void doStuff() {
sqr = (int) Math.sqrt(NUMBER);
sqrp1 = sqr + 1;
Thread[] t = new Thread[sqrp1];
//starting tasks
for (int i = 1; i < sqrp1; i++) {
final int it = i;
if (NUMBER % i == 0) {
final int e = i;
t[i] = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("sta"+e);
if (!checkContains(e)) {
addElement(e);
}
final int dividednumber = NUMBER / e;
if (!checkContains(dividednumber)) {
addElement(dividednumber);
}
}
});
t[i].start();
}
}
//calling join for tasks
for (int i = 1; i < sqrp1; i++) {
final int it = i;
if (NUMBER % i == 0) {
try {
System.out.println("sto"+i);
t[i].join();
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.out.println("xxx");
Collections.sort(dividors);
Integer[] arrayDividors = dividors.toArray(new Integer[0]);
for (int i = 0; i < arrayDividors.length; i++) {
System.out.println(arrayDividors[i]);
}
}
private synchronized void addElement(int element) {
dividors.add(element);
}
private synchronized boolean checkContains(int element) {
return dividors.contains(element);
}
}
你需要把它变成一个单一的原子操作
if (!checkContains(dividednumber)) {
addElement(dividednumber);
}
假设你有两条线
T1: if (!checkContains(dividednumber)) { // false
T2: if (!checkContains(dividednumber)) { // false
T1: addElement(dividednumber); // adds number
T2: addElement(dividednumber); // adds same number
如果您有一个没有重复项的加法器,则不会发生这种情况。针对此问题,dividednumber
对于任何两个线程都不应与从递增计数器获得的相同。所以添加相同的数字似乎不太可能。@Santosh一个数字理论上可以添加两次,但上限阻止了这一点。好的,但是checkContains是同步的,对吗?这是否意味着我应该通过synchronize(this){…}
来覆盖此代码?@fishontegrass正确。另一个线程可以在两个同步方法之间运行。仅仅因为这两种方法是线程安全的,并不意味着它们可以在任何组合中使用并且仍然是线程保存的。我编辑了我的问题,现在可以了吗@PeterLawrey,我应该介绍我的同步2种方法吗?顺便说一句,你的条件应该是
T1: if (!checkContains(dividednumber)) { // false
T2: if (!checkContains(dividednumber)) { // false
T1: addElement(dividednumber); // adds number
T2: addElement(dividednumber); // adds same number