一个线程更新变量而另一个线程读取它,我需要一些特殊的东西

时间:2014-03-15 07:35:30

标签: java android

我有一个具有“卡片”对象的课程。该类不断检查对象是否不再为null。只有一个其他线程可以更新此对象。我应该像下面的代码那样做吗?使用volatile?Syncronized?锁(我不知道如何使用真的)?您认为最简单的解决方案是什么?

Class A{

 public Card myCard = null;


 public void keepCheck(){

    while(myCard == null){
       Thread.sleep(100)
    }
    //value updated
     callAnotherMethod();
 }

另一个主题有以下内容:

public void run(){
     a.myCard = new Card(5);
 }

你有什么建议?

3 个答案:

答案 0 :(得分:0)

如果您打算对其进行轮询,则从另一个线程进行修改时,该变量需要是易变的,但更好的解决方案是使用wait() / notify()甚至Semaphore来保持你的另一个线程处于睡眠状态,直到初始化myCard变量。

答案 1 :(得分:0)

看起来你有一个经典的制作人/消费者案例。

您可以使用wait()/ notify()方法处理此情况。请参阅此处以获取示例:How to use wait and notify in Java?

或者在这里,更多示例:http://www.programcreek.com/2009/02/notify-and-wait-example/

答案 2 :(得分:0)

您应该使用正确的等待事件(请参阅Guarded Block教程),否则您可能会遇到“观察”线程在看到Card的完全初始化成员字段之前看到该引用的风险。同样wait()将允许线程休眠而不是在紧密的while循环中吸收CPU。

例如:

Class A {

    private final Object cardMonitor = new Object();
    private volatile Card myCard;

    public void keepCheck () {
        synchronized (cardMonitor) {
            while (myCard == null) {
                try {
                    cardMonitor.wait();
                } catch (InterruptedException x) {
                    // either abort or ignore, your choice
                }
            }
        }
        callAnotherMethod();
    }

    public void run () {
        synchronized (cardMonitor) {
            myCard = new Card(5);
            cardMonitor.notifyAll();
        }
    }

}

我在上面的示例中将myCard设为私有。我确实建议在这种情况下避免使用大量的公共字段,因为代码最终会变得很乱。

另请注意,您不需要 cardMonitor - 您可以使用A本身,但拥有单独的监视器对象可以让您更好地控制同步。 / p>

请注意,通过上述实现,如果在run()执行期间调用callAnotherMethod(),则会更改myCard,这可能会中断callAnotherMethod()(您未显示) 。在同步块中移动callAnotherMethod()是一种可能的解决方案,但您必须根据您的要求确定适当的策略。