Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么join()现在在这里工作?_Java_Multithreading_Join - Fatal编程技术网

Java 为什么join()现在在这里工作?

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

我试图在多个线程的帮助下,将从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 = 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。)
  • 线程1调用
    add(3)
  • JVM(线程1)读取/看到
    MyInteger
    具有值 ,并在添加操作过程中单独维护
  • 线程2调用
    add(5)
  • JVM(线程2)读取/查看
    MyInteger
    值为17,并在添加期间单独维护该值 操作
  • JVM(线程1和线程2)增加各自的 值,因此线程1有20个,线程2有22个
  • JVM(线程1)将20写回MyInteger中的原语
  • JVM(线程2)将22写回MyInteger中的原语
  • 您现在已经丢失了
    add(3)
    操作的结果,因为正确的原子操作将导致
    25
    作为最终值

    除了线程安全的重要性之外,最重要的是,即使是涉及原语的简单加法操作也不能作为单个原子操作执行。相反,它在JVM中被分解为更小的步骤,这允许并发线程相互竞争

    以下是wiki文章中(优秀)表格的屏幕截图,直观地展示了这一点:


    您的
    加入
    代码看起来正确。我怀疑您的代码遇到了
    竞赛危险

    当您有多个线程同时运行,所有线程都在修改共享资源时,您需要确保它们在执行修改时具有独占访问权限

    作为快速修复要确认这是一场数据竞赛,请尝试在
    MyInteger
    类中的
    add()
    方法中添加
    synchronized
    修饰符

    最终发生的是(对于一个双线程示例):

  • (假设
    MyInteger
    实例的初始值为17。)
  • 线程1调用
    add(3)
  • JVM(线程1)读取/看到
    MyInteger
    具有值 ,并在添加操作过程中单独维护
  • 线程2调用
    add(5)
  • JVM(线程2)读取/查看
    MyInteger
    值为17,并在添加期间单独维护该值 操作
  • JVM(线程1和线程2)增加各自的 值,因此线程1有20个,线程2有22个
  • JVM(线程1)将20写回MyInteger中的原语
  • JVM(线程2)将22写回MyInteger中的原语
  • 您现在已经丢失了
    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--;
    }
    }