我是同步的新手,并试图了解等待和通知的工作原理。
问题: -
程序执行2个线程 - T1& T2同时但基于输出T1先运行,执行问题(第一)方法,打印问题,设置标志(true),运行notify()方法,执行问题(第二)方法&进入等待方法。现在T2开始并执行。
我的代码:
package TestThread;
class Chat {
boolean flag = false;
public synchronized void Question(String msg) {
System.out.println("Question method = " + flag);
if (flag) {
try {
System.out.println("Question method wait start");
wait();
System.out.println("Question method wait finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag = true;
notify();
}
public synchronized void Answer(String msg) {
System.out.println("Answer method = " + flag);
if (!flag) {
try {
System.out.println("Answer method wait start");
wait();
System.out.println("Answer method wait finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(msg);
flag = false;
notify();
}
}
class T1 implements Runnable {
Chat m;
String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" };
public T1(Chat m1) {
this.m = m1;
new Thread(this, "Question").start();
}
public void run() {
for (int i = 0; i < s1.length; i++) {
m.Question(s1[i]);
}
}
}
class T2 implements Runnable {
Chat m;
String[] s2 = { "Hi", "I am good, what about you?", "Great!" };
public T2(Chat m2) {
this.m = m2;
new Thread(this, "Answer").start();
}
public void run() {
for (int i = 0; i < s2.length; i++) {
m.Answer(s2[i]);
}
}
}
public class MultiThread {
public static void main(String[] args) {
Chat m = new Chat();
new T1(m);
new T2(m);
}
}
结果: -
Question method = false
Hi
Question method = true
Question method wait start
Answer method = true
Hi
Answer method = false
Answer method wait start
Question method wait finish
How are you ?
Question method = true
Question method wait start
Answer method wait finish
I am good, what about you?
Answer method = false
Answer method wait start
Question method wait finish
I am also doing fine!
Answer method wait finish
Great!
答案 0 :(得分:0)
为什么在T1调用对象聊天的等待方法之前T2不会启动?
你有一个竞争条件。两个线程中的任何一个都将首先执行。由于它们共享一个Chat
实例,其方法为synchronized
,因此将阻塞,直到另一个实例解锁Chat
实例上的监视器。
第一次执行问题方法时,
notify()
方法是。{ 在调用时,聊天对象上没有wait()
(因为t2还没有 开始)。那么,哪个线程监听这个通知方法?
没有。
答案 1 :(得分:0)
1。)为什么在T1调用对象聊天的等待方法之前T2不会启动?
实际上T2在此之前就开始了,但你没有注意到,因为你没有任何记录声明出现。将System.out置于T2的run方法中并运行您的程序几次。在T1调用wait方法之前你会看到T2开始。请记住,T2无法进入Chat对象的Answer方法,因为在最终调用wait()之前,T1会获取其锁定。
要记住的另一件事是无法保证线程的启动顺序。仅仅因为T1.start出现在T2.start之前,并不意味着T1将始终首先启动。线程调度程序做出了这个决定。
2.)当第一次执行问题方法并调用notify()方法时,聊天对象上没有wait()(因为t2尚未启动)。所以,哪个线程监听这个通知方法。
- 如果没有等待呼叫,则通知不会影响任何线程。
答案 2 :(得分:0)
为什么在T1调用Object的wait方法之前T2不会启动 聊天。
你有一个相同的对象'm'并将其传递给不同的线程并且有方法级别同步,所以当'call'进入问题()时,整个对象将会锁定直到调用wait()因此将阻止answer方法。
第一次执行问题方法时,notify()方法是 调用时,聊天对象上没有wait()(因为t2还没有 开始)。所以,哪个线程监听这个通知方法。
notify()第一次没有意义,synchronized方法必须完成全部。如前所述,在问题()完成/释放锁定(调用wait())之前,不执行answer()