Java Timer无缘无故停止

时间:2015-02-24 19:46:18

标签: java linux timer raspberry-pi schedule

我是Java的新手,很抱歉,如果这个问题很简单。我的代码可能很乱。我在Java中为Raspberry Pi创建了一个在线广播播放器,我必须每10秒做一次POST请求来检查当前播放的歌曲是什么,如果歌曲发生了变化,我必须做一些事情(比如scrobble old song,update显示新的歌曲数据,存储播放会话到我的服务器等)。我为此创建了一个类:

public class Scrobbler implements Runnable, Commands, Observer {
    private TimeCounter counter;
    private Timer timer;
    private Radio radio;
    private List<Observer> observers;
    private final Object MUTEX= new Object();
    private int currentPlaySession;
    // And all other variables which I deleted before posting

    // Constructor
    public Scrobbler(TimeCounter _counter, Radio _radio)
    {
        currentTrack = null;
        counter = _counter;
        radio = _radio;
        timer = null;
        observers = new ArrayList<>();
        currentPlaySession = 0;
    }

    private void GetInfo()
    {
        // POST request to get current song playing
        // If song has changed, notify observers
    }

    public void Scrobble()
    {
        // POST request - Scrobble song to my website and last.fm
    }

    public void StartPlaySession()
    {
        // Again POST request to my website
    }

    public void EndPlaySession()
    {
        // Again POST request to my website
    }

    @Override
    public void start() {
        new Thread(this).start();
    }

    public void stop()
    {
        timer.cancel();
        timer.purge();
        timer = null;
    }

    @Override
    public void register(Observer obj) {
        if(obj == null) throw new NullPointerException("Null Observer");
        synchronized (MUTEX) {
            if(!observers.contains(obj)) observers.add(obj);
        }
    }

    @Override
    public void unregister(Observer obj) {
        synchronized (MUTEX) {
            observers.remove(obj);
        }       
    }

    @Override
    public void notifyObservers(String command) {
        for (Observer obj : observers) {
            obj.update(command);
        }
    }

    @Override
    public void run() {
        timer = new Timer();
        timer.schedule(new TimeOut(), 0, 10000);
        GetInfo();
        StartPlaySession();
    }

    public class TimeOut extends TimerTask
    {
        @Override
        public void run() {
            EndPlaySession();
            GetInfo();
        }   
    }

    @Override
    public void update(String command) {
        if ("RADIO_STARTED".equals(command))
        {
            this.start();
        }

        if ("RADIO_STOPPED".equals(command))
        {
            this.stop();
            if (this.currentTrack != null && this.counter.getTrackTime() >= 60)
                this.Scrobble();
            EndPlaySession();
        }
    }

    private void handleException(String message)
    {
        try {
            String timeStamp = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
            PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("/home/pi/OnlineRadio/error_log.txt", true)));
            out.println("(" + timeStamp + ") [SCROBBLER] - " + message + "\n\n\r");
            out.close();
        } catch (IOException e) {}

        this.stop();
        this.start();
    }
}

我在main方法中创建了一个新的Scrobbler实例,并将其注册为播放器的可观察对象。一旦我启动收音机,播放器将通过调用update()方法通知其观察者(包括Scrobbler类的实例)并转发&#34; RADIO_STARTED&#34;或&#34; RADIO_STOPPED&#34; (在启动或停止收音机后)。正如您在代码中看到的那样,在RADIO_STARTED上,调用start()方法,其中启动了新的Thread。这里可能不需要开始一个新的线程,因为它只启动计时器,但它也不应该是一个问题。启动计时器后,将调用TimeOut类中的每10秒方法run(),然后调用必要的方法。

此代码有效,但有时它会毫无理由地停止。应用程序的所有其他部分继续工作(音乐仍在播放,应用程序对按钮等作出反应),只是它没有更新歌曲,并且根本没有与我的网站进行任何通信,所以甚至没有调用这些方法,就像定时器停止一样。当我再次停止并启动收音机或更换电台时,它再次工作(正如您在代码中看到的那样,每次收音机停止时定时器将停止,定时器将在每次收音机启动时启动),但它会再次中断过了一段时间。

由于我在POST请求的那些方法中有很多try-catch块,起初我认为必须发生异常并杀死定时器线程所以我创建了handleException()方法,它将异常消息记录到a文件并重新启动此计时器(您可以在代码中看到),然后我处理这样的异常,例如:

try {
    writer.close();
} catch (IOException e) {
    this.handleException(e.getMessage());
}

但是当问题再次发生时,日志文件为空,这意味着甚至没有发生一个异常。每次歌曲改变时我也会尝试记录所有数据,一切都很好,它会在一段时间后无缘无故地停止。并且我无法找到发生的规律性,有时它会在几分钟后发生,有时如果在它休息之前工作几个小时。

这个应用程序在Raspberry Pi模型B上运行,我不知道这是否意味着什么,但它在JAR中,它从Pi开始(通过cron @reboot),因为我没有&#39 ;在这个Pi上有任何显示器或键盘/鼠标,所以应用程序必须从它开始并始终在后台运行。我使用SSH将JAR传输到Pi并读取日志文件。

在某处我读到Java计时器没有任何理由停止的情况并不少见。但是如何解决这个问题?

0 个答案:

没有答案
相关问题