英文:
synchronized keyword is giving the expected output but not satisfied with the order in which the method is called by different threads
问题
以下是实现了Runnable接口的三个类(线程)的代码部分:
public class Thread1 implements Runnable {
Shared s;
public Thread1(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 10 and 20 by " + Thread.currentThread().getName() + " is " + s.add(10, 20));
}
}
public class Thread2 implements Runnable {
Shared s;
public Thread2(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 100 and 200 by " + Thread.currentThread().getName() + " is " + s.add(100, 200));
}
}
public class Thread3 implements Runnable {
Shared s;
public Thread3(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 1000 and 2000 by " + Thread.currentThread().getName() + " is " + s.add(1000, 2000));
}
}
以下是被这些线程共享的对象类的代码部分:
public class Shared {
private int x;
private int y;
synchronized public int add(int a, int b) {
x = a;
y = b;
try {
System.out.println(Thread.currentThread().getName() + " is going into sleep state");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x + y;
}
}
最后,以下是如何启动线程并传递Shared对象的代码部分:
public static void main(String[] args) {
Shared s = new Shared();
Thread t1 = new Thread(new Thread1(s), "Thread-1");
Thread t2 = new Thread(new Thread2(s), "Thread-2");
Thread t3 = new Thread(new Thread3(s), "Thread-3");
t1.start();
t2.start();
t3.start();
}
请注意,我只提供了代码的翻译部分,没有包含其他内容。
英文:
Below are my 3 classes(threads) implementing Runnable interface:
public class Thread1 implements Runnable {
Shared s;
public Thread1(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 10 and 20 by " + Thread.currentThread().getName() + " is "+ s.add(10, 20));
}
}
public class Thread2 implements Runnable {
Shared s;
public Thread2(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 100 and 200 by " + Thread.currentThread().getName() + " is " + s.add(100, 200));
}
}
public class Thread3 implements Runnable {
Shared s;
public Thread3(Shared s){
this.s = s;
}
@Override
public void run() {
System.out.println("Sum of 1000 and 2000 by " + Thread.currentThread().getName() + " is " + s.add(1000, 2000));
}
}
And below is the class whose object is shared among these threads:
public class Shared {
private int x;
private int y;
synchronized public int add(int a, int b) {
x = a;
y = b;
try {
System.out.println(Thread.currentThread().getName() + "is going into sleep state");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x + y;
}
}
And finally this is how I'm starting threads and passing Shared object:
public static void main(String[] args) {
Shared s = new Shared();
Thread t1 = new Thread(new Thread1(s), "Thread-1");
Thread t2 = new Thread(new Thread2(s), "Thread-2");
Thread t3 = new Thread(new Thread3(s), "Thread-3");
t1.start();
t2.start();
t3.start();
}
This is the output I'm getting which is correct:
Thread-2is going into sleep state
Thread-1is going into sleep state
Sum of 100 and 200 by Thread-2 is 300
Thread-3is going into sleep state
Sum of 10 and 20 by Thread-1 is 30
Sum of 1000 and 2000 by Thread-3 is 3000
But if you see here, Thread-1 started executing the add method(which is synchronized) before Thread-2 finished its job.
Since Thread-2 went into sleep state so it also took the lock with itself and no other thread should be allowed to enter the add(...) method. Thread-1 or Thread-3 could only start executing add(...) method after Thread-2 is done. So, the output I was expecting was :
Thread-2is going into sleep state
Sum of 100 and 200 by Thread-2 is 300
Thread-1is going into sleep state
Sum of 10 and 20 by Thread-1 is 30
Thread-3is going into sleep state
Sum of 1000 and 2000 by Thread-3 is 3000
Please tell what I'm doing wrong or this is how the output will be, if yes, please tell why.
答案1
得分: 2
以下是翻译好的部分:
原因是 System.out.println()
很慢。
您在 run()
方法内部以及 add()
方法内部都使用它发送消息。不能保证 sysout 中的消息一致。
我已经重写了 Shared
如下:
public class Shared {
private int x;
private int y;
synchronized public int add(int a, int b) {
x = a;
y = b;
try {
long now = System.currentTimeMillis() - start;
Thread.sleep(1000);
// 注意先是 sleep,然后是 sysout
System.out.println(Thread.currentThread().getName() + " 计算发生在时间 " + now);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x + y;
}
public static long start;
public static void main(String[] args) {
start = System.currentTimeMillis();
Shared s = new Shared();
Thread t1 = new Thread(new Thread1(s), "Thread-1");
Thread t2 = new Thread(new Thread2(s), "Thread-2");
Thread t3 = new Thread(new Thread3(s), "Thread-3");
t1.start();
t2.start();
t3.start();
}
}
现在每个线程看起来如下:
public class Thread1 implements Runnable {
Shared s;
public Thread1(Shared s) {
this.s = s;
}
@Override
public void run() {
int result = s.add(10, 20);
long now= System.currentTimeMillis()-Shared.start;
System.out.println(Thread.currentThread().getName() + " 计算 10 和 20 的总和为 " + result+ ",发生在 "+ now);
}
}
生成以下输出:
Thread-1 计算发生在时间 2
Thread-1 计算 10 和 20 的总和为 30,发生在 1005
Thread-2 计算发生在时间 1005
Thread-2 计算 100 和 200 的总和为 300,发生在 2006
Thread-3 计算发生在时间 2006
Thread-3 计算 1000 和 2000 的总和为 3000,发生在 3007
每个线程都在 add()
中被阻塞,只有在稍后显示结果时,下一个线程才开始计算。
请注意,现在 add()
中首先是 sysout(这很慢),而且它发生在睡眠期间,这给了它足够的时间。
英文:
The reason is that the System.out.println()
is very slow.
You use it to send messages from both within the run() methods and also from within add()
. There is no guarantee that the messages in sysout coincide.
I have rewritten Shared
as follows:
public class Shared {
private int x;
private int y;
synchronized public int add(int a, int b) {
x = a;
y = b;
try {
long now = System.currentTimeMillis() - start;
Thread.sleep(1000);
// notice FIRST sleep and THEN sysout
System.out.println(Thread.currentThread().getName() + " calculation has taken place at time " + now);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x + y;
}
public static long start;
public static void main(String[] args) {
start = System.currentTimeMillis();
Shared s = new Shared();
Thread t1 = new Thread(new Thread1(s), "Thread-1");
Thread t2 = new Thread(new Thread2(s), "Thread-2");
Thread t3 = new Thread(new Thread3(s), "Thread-3");
t1.start();
t2.start();
t3.start();
}
}
with each of the threads now looking like:
public class Thread1 implements Runnable {
Shared s;
public Thread1(Shared s) {
this.s = s;
}
@Override
public void run() {
int result = s.add(10, 20);
long now= System.currentTimeMillis()-Shared.start;
System.out.println("Sum of 10 and 20 by " + Thread.currentThread().getName() + " is " + result+ " found at "+ now);
}
}
generating the following output:
Thread-1 calculation has taken place at time 2
Sum of 10 and 20 by Thread-1 is 30 found at 1005
Thread-2 calculation has taken place at time 1005
Sum of 100 and 200 by Thread-2 is 300 found at 2006
Thread-3 calculation has taken place at time 2006
Sum of 1000 and 2000 by Thread-3 is 3000 found at 3007
each thread blocked in add()
as it should.
Only when later the result is displayed, the next thread has already started calculating.
Notice that add()
now there is first the sysout (which is slow) and it happens during the sleep, which gives it enough time.
答案2
得分: 1
您需要按照以下方式同步 `s`:
@Override
public void run() {
synchronized (s) {
System.out.println("Sum of 10 and 20 by " + Thread.currentThread().getName() + " is " + s.add(10, 20));
}
}
在 Thread2
和 Thread3
类中也要这样做。查看 此链接 以获取解释。
英文:
You need to synchronize s
as shown below:
@Override
public void run() {
synchronized (s) {
System.out.println("Sum of 10 and 20 by " + Thread.currentThread().getName() + " is " + s.add(10, 20));
}
}
Do this in the classes, Thread2
and Thread3
as well. Check this for an explanation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论