Java:线程中的NotifyObserver和DeadLock

时间:2012-03-26 16:16:12

标签: java multithreading model-view-controller deadlock

我遇到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()是一种不好的做法...... 建议?

谢谢!

2 个答案:

答案 0 :(得分:3)

看起来你在这里有一些逻辑错误:

  1. runMyJob()您正在呼叫model.changeStatus(123)
  2. notifyObservers()
  3. 中调用Observable
  4. 通过致电MyController.update()
  5. 通知观察员
  6. 然后在线程上尝试join()
  7. 由于线程是调用update()的线程,因此它正试图加入自己,这显然不会起作用。我让主线程在开始后进行连接:

    myJob.start();
    myJob.join();
    

    您还可以在更新期间设置某种值(可能是volatile intAtomicInteger),然后主线程可以读取这些值。

    如果您编辑问题以告诉我们您要完成的工作,我会调整答案以提供更好的建议。

答案 1 :(得分:3)

您显然正在尝试join()当前主题(如果您将myJob.join()替换为System.out.println( Thread.currentThread() ),则可以自行查看),这不是一个好主意,线程将永远被卡住,或直到其他人从外部中断它。

而不是join(),只需致电interrupt(),就没有什么可耻的了。 (虽然它是否会产生任何影响取决于runMyJob()

中的其他内容

更新:我只能假设您为了简洁而编辑了部分代码,但如果MyController遇到退出值123而不是停止更新线程,那么它真的没有做任何事情,那么整个建筑是不必要的。你应该简单地从runMyJob()方法返回而不设置任何东西,线程将正常停止。