在同步块中使用 wait()



我偶然发现了一段Android服务类中的一段代码,该代码具有带有等待语句的同步块。 代码如下:

public class MyService extends IntentService{
protected void onHandleIntent(Intent intent){
synchronized(this){
try{
wait(10000);         
}catch(InterruptedException e){
e.printStackTrack();
}
String message = intent.getStringExtra("Message");
showMessage(message);
}
}
}

上面的代码是否意味着任意数量的线程都可以进入synchronized块?我知道sleepThread置于"已阻止"状态。这和Thread呼叫wait()一样吗? 基本上当我将文本传递给Service时,我希望Service等待 10 秒,然后在LogCat中显示消息。 我从来没有使用过wait()所以任何人都可以向我解释上面的代码在做什么吗?

你的陈述"任意数量的线程都可以进入synchronized块"是错误的。

从理论上讲,如果一个线程在synchronized块内,这会阻止其他线程进入。这在IntentService的情况下是不可能的,因为IntentService使用单个工作线程来处理工作负载。

调用wait()是一种线程同步方法,而不是延迟方法。这与调用sleep()不同,后者只是在特定时间内阻塞线程。 当你调用wait()时,这会阻塞线程,直到另一个线程调用notify(),用于协调多个线程之间的活动。wait(10000)阻塞线程,直到从另一个线程调用任一notify()或直到超时到期(在本例中为 10 秒(。所以这看起来应该在某处有另一个线程在IntentService对象上调用notify()来唤醒它。

这里还有一个与使用notify()wait()相关的额外复杂性。为了调用这些方法中的任何一个,必须首先在对象的监视器上获取锁(通过使用synchronized(。这意味着对wait()notify()的调用必须在synchronized块内或在对象上synchronizedsynchronized方法内。

调用wait()线程实际上释放对象上的锁。这意味着线程在synchronized块/方法中被阻塞,但在等待时它没有对对象的锁定。调用notify()(或超时已过期(后,线程将重新获得对象的锁并继续执行。

有关在 Java 中使用notify()wait()的更多信息,请搜索这些术语并阅读相关内容。

如果这段代码应该

做的只是延迟 10 秒,然后向 logcat 编写一些东西,那么这段代码就非常复杂了。您可以只调用sleep()而不是不需要synchronized语句的wait()。但是,正如另一张海报所指出的那样,如果经常调用此Service,这将创建积压工作,因为对onHandleIntent()的每个调用都将延迟 10 秒,并且由于只有 1 个工作线程,因此所有调用都是序列化的。示例:在 10:00:00 调用startService(),logcat 中的条目将显示在 10:00:10。如果在 10:00:01 对startService()进行了另一次调用,则该条目直到 10:00:20 才会出现在 logcat 中,因为对onHandleIntent()的第二次调用要到 10:00:10 才会发生。

你的问题的一部分涉及多线程,这是一个相当复杂的话题。我建议从这样的教程开始,以获得这些答案。

上面的代码将用于将日志条目延迟 10 秒。但是,IntentService只有 1 个工作线程,因此如果连续请求每 10 秒发生一次以上,则它们将被积压。

由于仅涉及 1 个工作线程,因此使用同步确实是错误的答案。为什么不放弃意图服务,而只是使用CountDownTimer在UI线程上完成所有这些操作?

final String msg = intent.getStringExtra("Message");
new CountDownTimer(10000, 10000) {
@Override
public void onTick(long millisUntilFinished) {}
@Override
public void onFinish()  {
showMessage(msg);
}
}.start();

这样,您就可以利用 Android 的内置消息队列系统来创建并行执行的外观,而无需多线程的复杂性。

最新更新