我开始两个线程T1打印1,3,5,.....和线程两个T2打印2,4,6 ....下面是执行它的代码。
CREATE TABLE accommodation_service(
id ............,
accommodation_id ............,
service_id ............,
FOREIGN KEY (accommodation_id)
REFERENCES accommodation(id)
ON DELETE CASCADE,
FOREIGN KEY (service_id)
REFERENCES service(id)
ON DELETE CASCADE,
)
输出如下:
public class T1T2Print {
public static void main(String[] args) {
Counter c = new Counter();
c.count = 1;
printThread t1 = new printThread(c);
Thread T1 = new Thread(t1);
T1.setName("T1");
printThread t2 = new printThread(c);
Thread T2 = new Thread(t2);
T2.setName("T2");
T2.start();
T1.start();
}
}
class printThread implements Runnable {
public Counter count;
public int reminder;
public printThread(Counter count) {
this.count = count;
}
public void run() {
for (int i = 1; i <= 5; i++) {
synchronized (count) {
String name = Thread.currentThread().getName();
if (count.count % 2 != 0 && !name.equals("T1")) {
try {
count.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(name + " :: " + count.count);
count.count++;
count.notify();
}
if (count.count % 2 == 0 && !name.equals("T2")) {
try {
count.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(name + " :: " + count.count);
count.count++;
count.notify();
}
}
}
}
}
但是当我将启动线程的顺序更改为
时T1 :: 1
T2 :: 2
T1 :: 3
T2 :: 4
T1 :: 5
T2 :: 6
T1 :: 7
T2 :: 8
T1 :: 9
T2 :: 10
输出更改如下,为什么会出现此行为
T1.start();
T2.start();
答案 0 :(得分:2)
让我们在System.out.println(name + " :: waits");
来电之前添加count.wait()
。
然后是第一个案例日志:
T2 :: waits
T1 :: 1
T1 :: waits
T2 :: 2
T2 :: waits
T1 :: 3
T1 :: waits
T2 :: 4
T2 :: waits
T1 :: 5
T1 :: waits
T2 :: 6
T2 :: waits
T1 :: 7
T1 :: waits
T2 :: 8
T2 :: waits
T1 :: 9
T1 :: waits
T2 :: 10
第二案例日志:
T1 :: 1
T1 :: waits
T2 :: 2
T2 :: 3
T1 :: 4
T1 :: 5
T1 :: 6
T1 :: 7
T1 :: 8
T1 :: 9
T1 :: 10
T1 :: 11
T2 :: 12
T2 :: 13
T2 :: 14
T2 :: 15
T2 :: 16
T2 :: 17
T2 :: 18
正如你在第二种情况下所看到的,线程不会睡觉。为什么?因为在第二种情况下,每个线程增加计数器两次(第一次if
一次,第二次if
一次)(并以同步方式执行)。 (我可以假设你没有想要这个逻辑,而这就是你犯的错误。)案例之间有什么区别?在第一种情况下T2
更早开始并且在第一种情况下等待,如果被通知则它被唤醒并且进入第二种情况,即它每次迭代仅增加(并打印)计数器一次。这就是原因。
答案 1 :(得分:1)
if
条件存在一些问题。对于每次迭代,计数器可以递增两次。
举一个例子,当计数器为2时,你的T2
线程,将值递增两次。 count.count % 2 != 0
为false,因此执行else并且计数器递增。然后,第二个if也是false,因为counter现在是3并且count.count % 2 == 0
是false,所以第二个else也被执行并且计数器增加并且你得到意外的输出。
您的if
语句可以修改为以下内容:
public void run() {
for (int i = 1; i <= 5; i++) {
synchronized (count) {
String name = Thread.currentThread().getName();
if (name.equals("T1")) {
while (count.count % 2 == 0) {
try {
count.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + " :: " + count.count);
count.count++;
count.notify();
} else if (name.equals("T2")) {
while (count.count % 2 != 0) {
try {
count.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + " :: " + count.count);
count.count++;
count.notify();
}
}
}
}