我是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计时器没有任何理由停止的情况并不少见。但是如何解决这个问题?