多线程_无法获得预期的输出

huangapple go评论61阅读模式
英文:

MultiThread_Unable to get the expected output

问题

package programs;

public class TestThreads {
    
    public static void main(String[] args) {
        ThreadOne t1 = new ThreadOne();
        ThreadTwo t2 = new ThreadTwo();
        Thread one = new Thread(t1);
        Thread two = new Thread(t2);
        
        one.start();
        two.start();
    }

}

class Accum{
    
    private static Accum a = new Accum();
    private int counter = 0;
    
    private Accum() {
    }
    
    public static Accum getAccum() {
        return a;
    }
    
    public void updateCounter(int add) {
        counter +=add;
    }
    
    public int getCount() {
        return counter;
    }
}

class ThreadOne implements Runnable{
    Accum a = Accum.getAccum();

    @Override
    public void run() {
        for(int x=0;x<98;x++) {
            a.updateCounter(1000);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                                
        }
        System.out.println("one "+ a.getCount());
    }
    
}

class ThreadTwo implements Runnable{
    
    Accum a = Accum.getAccum();
    @Override
    public void run() {
    for(int x=0;x<99;x++) {
        a.updateCounter(1);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println("two "+ a.getCount());    
    }
}

预期输出应该是以下内容:

<pre>One 98098
Two 98099</pre>
但是我得到的值对于One和Two都是相同的。
这是预期的吗?还是两者应该得出不同的值?
当涉及线程优先级时,尽管 JVM 调度器负责选择首先执行哪个线程,但是对于这个程序的结果如何呢?
其中有两个 void run 程序,一个使用循环次数为 98,另一个为 99,这应该得出两个不同的值,否则相同。
英文:
```
package programs;
public class TestThreads {
public static void main(String[] args) {
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class Accum{
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public void updateCounter(int add) {
counter +=add;
}
public int getCount() {
return counter;
}
}
class ThreadOne implements Runnable{
Accum a = Accum.getAccum();
@Override
public void run() {
for(int x=0;x&lt;98;x++) {
a.updateCounter(1000);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(&quot;one &quot;+ a.getCount());
}
}
class ThreadTwo implements Runnable{
Accum a = Accum.getAccum();
@Override
public void run() {
for(int x=0;x&lt;99;x++) {
a.updateCounter(1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(&quot;two &quot;+ a.getCount());	
}
}
```

The expected output should be as below
<pre>One 98098
Two 98099</pre>
But I am getting values same for both One and Two.
Is this expected or both should result in different values?
When it comes to thread priorities eventhough the jvm scheduler takes the role to choose the turn of which thread should execute first, what about the results of this program where two void run programs of for loop with 98 and 99 which should result in two different values else the same

答案1

得分: 3

这是因为共享数据没有同步。

要解决这个问题,在那些涉及到共享数据的方法上使用 synchronized,以使 Accum 类成为线程安全的。

示例:

class Accum{
    
    private static Accum a = new Accum();
    
    private int counter = 0;
    
    private Accum() {
        
    }
    
    public static Accum getAccum() {
        
        return a;
    }
    
    public synchronized void updateCounter(int add) {
        counter += add;
    }
    
    public synchronized int getCount() {
        
        return counter;
    }
}
英文:

This is because shared data is NOT synchronized.

To resolve this problem, use synchronized on methods those touch the shared data, to make Accum class Thread-Safe.

example:

class Accum{
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public synchronized void updateCounter(int add) {
counter +=add;
}
public synchronized int getCount() {
return counter;
}
}

答案2

得分: 0

或许将 Accum 类中的方法和字段设为静态的,因为这样它们会保存在一个通用的地方,而不是一个实例中...

代码:

class Accum {
    
    private static Accum a = new Accum();
    
    private static int counter = 0;
    
    private Accum() {
        
    }
    
    public static Accum getAccum() {
        
        return a;
    }
    
    public static void updateCounter(int add) {
        counter += add;
    }
    
    public static int getCount() {
        
        return counter;
    }
}

class ThreadTwo implements Runnable {
    
    @Override
    public void run() {
        for (int x = 0; x < 99; x++) {
            Accum.updateCounter(1);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("two " + Accum.getCount());   
    }
}

class ThreadOne implements Runnable {
    
    @Override
    public void run() {
        for (int x = 0; x < 98; x++) {
            Accum.updateCounter(1000);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("one " + Accum.getCount());
    }
}

我在Java方面经验不太丰富,所以这可能不起作用...
[编辑] 我已经测试过了,我相信它是可行的

英文:

Maybe make the methods and fields in the Accum class static, because then it is saved in a general place and not an instance...

Code:

class Accum{
private static Accum a = new Accum();
private static int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public static void updateCounter(int add) {
counter +=add;
}
public static int getCount() {
return counter;
}
}
class ThreadTwo implements Runnable{
@Override
public void run() {
for(int x=0;x&lt;99;x++) {
Accum.updateCounter(1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(&quot;two &quot;+ Accum.getCount());   
}
}
class ThreadOne implements Runnable{
@Override
public void run() {
for(int x=0;x&lt;98;x++) {
Accum.updateCounter(1000);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(&quot;one &quot;+ Accum.getCount());
}
}

I am not very experienced in Java yet, so this might not work...
[EDIT] I tested it and I believe it works

huangapple
  • 本文由 发表于 2020年9月20日 08:24:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/63974498.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定