监听数据,使用while(true)是正确的解决方案吗?Java

5

我遇到了一个问题,希望这里有人能帮助我。目前,我在我的程序中使用了太多的while(true)循环,所以它运行得有点慢。

我不确定我是否在代码上做错了什么,或者这是唯一的解决方案。

有一个类从另一个类接收数据(double),想要启动一个while循环,只有在数据不为0时才应该运行。这里是一些我的代码:

while (true) {
        while (kWh != 0) {
            try {
                queue.put(kWh);
            } catch (InterruptedException e) {                  
                System.out.println("Could not put data into queue");
            }
            kWh = 0;
        }   
    }





@Override
public void SendPower(double power_data) throws RemoteException {
    ReceivePowerData.kWh = power_data;              
}

如您所见,当SendPower方法运行时,kWh变量会得到更新。 当此变量不为0时,我希望while循环运行并将值插入队列。 我的问题是我正在使用while(true),因此即使没有接收到数据,它仍在运行该循环,这是一种浪费。
我还能做什么? 有什么想法吗?
更新
我已尝试使用wait()方法,并且似乎有效,它等待...但我不知道如何实现应该启动它的notify()方法。
代码:
synchronized (this) {
        System.out.println("Wait for response from sensor");
        try {
            wait();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println("Continue");

        while (kWh != 0) {
            try {
                queue.put(kWh);
            } catch (InterruptedException e) {                  
                System.out.println("Could not put data into queue");
            }
            kWh = 0;
        }   

    }

然后我尝试用方法来编写它,但我真的认为这是错误的..

@Override
public void SendPower(double power_data) throws RemoteException {
    ReceivePowerData.kWh = power_data;  

    synchronized (this) {
        notify();   
    }

}

当其他程序调用 SendPower 方法时,它应该运行,并且应该启动,但是这并没有起作用...我接近了吗?


5
在搜索引擎中查找“notifying an object's monitor”:这将指引你朝正确的方向前进。 - Bathsheba
我不确定你的意思是什么,请给个提示吗?我应该搜索什么关键词呢?:=? - Raaydk
我给你的句子是准确的。前十名中出现了一些有用的文章。有很多术语需要你掌握,我的句子最终对你来说会意义重大。 - Bathsheba
1
请查看 SynchronousQueue http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/SynchronousQueue.html - Alex Salauyou
内部 while 循环不会进入循环,但是 while(true) 会一直运行。你应该使用 break 或者一些布尔变量来控制。 - newuserua_ext
Bathsheba,你能看一下更新部分吗?我尝试使用wait和notify,但当notify运行时,它不会启动while循环。 - Raaydk
3个回答

5
你可以使用观察者模式。Java有标准接口来实现它。
Java中有很多关于这种模式的教程。

http://en.wikipedia.org/wiki/Observer_pattern http://www.tutorialspoint.com/design_pattern/observer_pattern.htm

这是一个非常简单的示例。

import java.util.Observable;
import java.util.Observer;
import java.util.Random;

public class ObserverPattern {
    private static class PowerObserverable extends Observable implements Runnable {

        public void run() {
            Random random = new Random();
            for (int x = 0; x < 10; x++) {
                double kwh = random.nextDouble() * 4;
                setChanged();
                notifyObservers(kwh);
            }
        }
    }

    // Make sure this class is thread safe
    private static class PowerObserver implements Observer {
        @Override
        public void update(Observable o, Object kwh) {
            System.out.println(kwh);
        }
    }

    public static void main(String[] args) {
        PowerObserverable observerable = new PowerObserverable();
        observerable.addObserver(new PowerObserver());

        new Thread(observerable).start();
    }
}

标准接口有哪些?第二个链接只使用POJOs。 - weston
java.util.Observer 和 java.util.Observable - Leon
如果他提供了实际的代码示例,那么这可能是一个很好的答案。 - Joop
维基百科上的Java示例非常简洁,无论如何我都会添加一个代码片段。 - Leon

0

使用Guarded Method

请注意,队列仅在synchronized方法中访问,因此不需要是同步队列。

private final Queue<Integer> queue = ArrayDeque<Integer>();

public synchronized void addKWh(int kwh){
   queue.put(kWh);
   notifyAll(); //tell other thread queue has something
}

//running on other thread
public synchronized void efficientQueueProcessor() { 
    while (true) { //really should have an exit condition
        Integer kwh = null;
        synchronized { //mainly because wait() must be in sync, but also for queue
            Integer kwh = queue.poll();
            if (kwh == null) {
              //queue is empty
              wait(); //thread will wait here efficiently until something is added
              continue; //so null is not processed
            }
        }
        processFigure(kwh); // out of sync block
    }
}

public void processFigure(int kwh){
    // do work with kwh
}

调用一个方法来添加,设置公共字段是不好的形式:

@Override
public void SendPower(double power_data) throws RemoteException {
    ReceivePowerData.addKWh(power_data);
}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接