Java 为什么join()现在在这里工作?
我试图在多个线程的帮助下,将从1到n的所有数字相加 这是我的帖子:Java 为什么join()现在在这里工作?,java,multithreading,join,Java,Multithreading,Join,我试图在多个线程的帮助下,将从1到n的所有数字相加 这是我的帖子: public class MyThread implements Runnable { //Limits int lowerLimit; int upperLimit; MyInteger result; //Constructor public MyThread(int lowerLimit, int upperLimit, MyInteger result){ this.lowerLimit = lowerLimi
public class MyThread implements Runnable {
//Limits
int lowerLimit;
int upperLimit;
MyInteger result;
//Constructor
public MyThread(int lowerLimit, int upperLimit, MyInteger result){
this.lowerLimit = lowerLimit;
this.upperLimit = upperLimit;
this.result = result;
}
@Override
public void run() {
//Sums up the numbers in the given interval
for(int i= lowerLimit; i <= upperLimit;i++){
result.add(i);
}
}
}
您的
join
代码看起来正确。我怀疑您的代码遇到了竞赛危险
:
当您有多个线程同时运行,所有线程都在修改共享资源时,您需要确保它们在执行修改时具有独占访问权限
作为快速修复要确认这是一场数据竞赛,请尝试在MyInteger
类中的add()
方法中添加synchronized
修饰符
最终发生的是(对于一个双线程示例):
MyInteger
实例的初始值为17。)add(3)
MyInteger
具有值
,并在添加操作过程中单独维护add(5)
MyInteger
值为17,并在添加期间单独维护该值
操作add(3)
操作的结果,因为正确的原子操作将导致25
作为最终值
除了线程安全的重要性之外,最重要的是,即使是涉及原语的简单加法操作也不能作为单个原子操作执行。相反,它在JVM中被分解为更小的步骤,这允许并发线程相互竞争
以下是wiki文章中(优秀)表格的屏幕截图,直观地展示了这一点:
您的
加入
代码看起来正确。我怀疑您的代码遇到了竞赛危险
:
当您有多个线程同时运行,所有线程都在修改共享资源时,您需要确保它们在执行修改时具有独占访问权限
作为快速修复要确认这是一场数据竞赛,请尝试在MyInteger
类中的add()
方法中添加synchronized
修饰符
最终发生的是(对于一个双线程示例):
MyInteger
实例的初始值为17。)add(3)
MyInteger
具有值
,并在添加操作过程中单独维护add(5)
MyInteger
值为17,并在添加期间单独维护该值
操作add(3)
操作的结果,因为正确的原子操作将导致25
作为最终值
除了线程安全的重要性之外,最重要的是,即使是涉及原语的简单加法操作也不能作为单个原子操作执行。相反,它在JVM中被分解为更小的步骤,这允许并发线程相互竞争
以下是wiki文章中(优秀)表格的屏幕截图,直观地展示了这一点:
您应该使用ExecutorService/Executors..您的
MyInteger
类是什么样子的?这看起来像是比赛条件@约书亚,遗嘱执行人只会让潜在的问题更难找到。简单线程没有问题。您应该使用ExecutorService/Executors。您的MyInteger
类是什么样子的?这看起来像是比赛条件@约书亚,遗嘱执行人只会让潜在的问题更难找到。简单的线程没有问题,就是这样!我没想到简单的计算会有竞争条件。现在我添加了synchronized,它可以工作了,但是:通过这个,整个多线程计算失去了意义,不是吗?如果它一直等待,直到另一个线程将其编号添加到结果中。我不想用电话。你知道如何优化它吗?你完全正确!所以你的下一个问题应该是,“什么时候使用多个线程才有意义?”答案是,当活动需要很长时间时。这里有一个提示:你需要把数字从1加到20,然后有两个人来做。你可以给他们一个特定的任务/输入,他们只能返回给你一次结果。您如何优化它们的工作方式来实现这一点?使用MyInteger数组,每个线程都有自己的MyInteger,怎么样。在所有线程的join()之后,可以构建MyInteger[]的和,它应该工作得更快,并利用多线程的优势。所以在你的例子中,人1为自己得到一个结果,人2为自己得到一个结果。两人计算完之后,他们把结果加起来,这就是全部的总和。这是完全正确的。因此,您需要创建一个与线程[]
大小相同的MyInteger[]
,并为每个线程
提供自己的MyInteger
索引。然后,在您的join()
调用之后,您(在主线程上,它是唯一一个运行的线程)在MyInteger[]
上循环并将值相加。这个过程通常被引用
public class Sum {
public static long sumThreads(int numberThreads, int n) {
Thread[] threads = new Thread[numberThreads];
MyInteger result = new MyInteger(0);
// Creates new threads and starts them
for (int i = 0; i < numberThreads; i++) {
threads[i] = new Thread(new MyThread(i * n / numberThreads + 1,
(i + 1) * n / numberThreads, result));
threads[i].start();
}
// Waits for all thread to continue with the return
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return result.getValue();
}
public static void main(String[] args) {
System.out.println(sumThreads(10, 1000));
}
}
public MyInteger(int value) {
this.value = value;
}
public long getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void add(int summand){
value += summand;
}
public void sub(int decr){
value -= decr;
}
public void increase(){
value++;
}
public void decrease(){
value--;
}
}