我仍然是一个java新手,并试图玩学习线程。我的问题是它没有循环5次。它运行一次并退出。我使用a.class来锁定类对象,这样两个线程都锁定在同一个对象监视器上。
class a implements Runnable {
Thread thr;
int count;
String time;
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tick";
System.out.println(time);
notify();
while (time == "Tock") {
wait();
}
}
} catch (Exception e) {
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tock";
System.out.println(time);
notify();
while (time == "Tick") {
wait();
}
}
} catch (Exception e) {
}
}
}
}
}
public class b {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
答案 0 :(得分:3)
在这里,您可以使用原始代码:
class a implements Runnable {
Thread thr;
int count;
static String time = "Tock";
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
while (time.equals("Tock")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tock";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
while (time.equals("Tick")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tick";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
问题是当你在wait
对象上持有锁时,你在隐式notify
对象上调用this
和a.class
,因此你必须调用wait/notify
上的a.class
。就是这样。
我还进行了一次小型重组,因为我假设您希望它们以交替的顺序打印Tick
和Tock
,对吗?
答案 1 :(得分:2)
在比较字符串(和一般对象)时,应使用equals
而不是==
(通常为基元保留):while(time.equals("Tock"))
。对于字符串,==
通常会导致false
当你想要它(并认为它应该)返回true
,因此你的循环将在预期之前退出。
答案 2 :(得分:2)
为什么你只循环一次的答案就是你在一个未锁定的对象上调用notify()
,因此抛出IllegalMonitorStateException
并被空的catch语句捕获。
这是一种方法。不是说这是最好的。我试着让它贴近你的代码:
public class TickTock {
static final int N = 4;
Object lock = new Object();
int token;
class Worker extends Thread {
int id;
Worker(int id) {
this.id = id;
}
@Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (id != token%N) lock.wait();
System.out.println(id + " " + i);
token++;
lock.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void start() {
for (int i = 0; i < N; i++) {
new Worker(i).start();
}
}
public static void main(String[] args) {
new TickTock().start();
}
}