我遇到Observer-Pattern和使用线程死锁的问题。
package observerDeadLock;
import java.util.Observable;
public class MyModel extends Observable {
Integer foo;
public MyModel() {
foo = 0;
}
public void changeStatus(Integer newStatus) {
foo = newStatus;
notifyObservers(newStatus);
}
}
package observerDeadLock;
public class Job extends Thread {
public MyModel model;
public Job(MyModel model) {
super();
this.model = model;
}
public void run() {
prepareJob();
runMyJob();
}
private void runMyJob() {
// Some stuff
Integer choice = 1;
if (choice == 3) {
return;
}
else if (choice == 2) {
return;
}
else if (choice == 1) {
model.changeStatus(123); // Set a particalar status that MyController receive as wrong!
// PROBLEM: The Controller listen the changeStatus(123) of notifyObserver of MyModel and call a join() because I want the thread join and quit()
return; // <<- NEVER EXECUTED! join(timeout) isn't the solution IHMO...s
}
return;
}
private void prepareJob() {
// Do some stuff
}
package observerDeadLock;
import java.util.Observable;
import java.util.Observer;
public class MyController implements Observer {
private Job myJob;
private MyModel model;
public MyController() {
}
public void startJob() {
model = new MyModel();
model.addObserver(this);
myJob = new Job(model);
myJob.start();
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof MyModel) {
if (((Integer) arg) == 1) {
// do other stuff
}
else if (((Integer) arg) == 2) {
// do other stuff
}
else if (((Integer) arg) == 123) { // 123 => Wrong state for myController, so must stop Job
// Stop myJob!!!
try {
//myJob.join(timeout); // isn' the solution IHMO
myJob.join(); // PROBLEM HERE!!! In job, the "return" statment is locked in changeStatus() -> myModel.notifyobserver() that lock here in JOIN();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
我可以做些什么来解决这个问题?我认为使用Thread.join()而不是Thread.interrupt()是一种不好的做法...... 建议?
谢谢!
答案 0 :(得分:3)
看起来你在这里有一些逻辑错误:
runMyJob()
您正在呼叫model.changeStatus(123)
notifyObservers()
Observable
MyController.update()
join()
。由于线程是调用update()
的线程,因此它正试图加入自己,这显然不会起作用。我让主线程在开始后进行连接:
myJob.start();
myJob.join();
您还可以在更新期间设置某种值(可能是volatile int
或AtomicInteger
),然后主线程可以读取这些值。
如果您编辑问题以告诉我们您要完成的工作,我会调整答案以提供更好的建议。
答案 1 :(得分:3)
您显然正在尝试join()
当前主题(如果您将myJob.join()
替换为System.out.println( Thread.currentThread() )
,则可以自行查看),这不是一个好主意,线程将永远被卡住,或直到其他人从外部中断它。
而不是join()
,只需致电interrupt()
,就没有什么可耻的了。 (虽然它是否会产生任何影响取决于runMyJob()
)
更新:我只能假设您为了简洁而编辑了部分代码,但如果MyController
遇到退出值123
而不是停止更新线程,那么它真的没有做任何事情,那么整个建筑是不必要的。你应该简单地从runMyJob()
方法返回而不设置任何东西,线程将正常停止。