我偶然发现了Android Service类中的一段代码,该代码具有带有等待语句的同步块。 代码如下:
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
块?我知道sleep
会将Thread
置于“已阻止”状态。 Thread
调用wait()
是否一样?
基本上,当我向Service
传递文本时,我希望Service
等待10秒,然后在LogCat
中显示消息。
我从来没有用过wait()
,所以有人可以向我解释以上代码在做什么吗?
答案 0 :(得分:0)
部分问题涉及多线程,这是一个非常复杂的主题。我建议从tutorial like this one开始获得这些答案。
以上代码将延迟日志输入10秒。但是,IntentService
只有1个工作线程,因此如果连续请求的发生频率超过每10秒一次,则将积压连续请求。
因为只涉及1个工作线程,所以使用同步确实是错误的答案。为什么不放弃IntentService,而仅使用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的built-in message queueing system来创建并行执行的外观,而不必担心多线程的复杂性。
答案 1 :(得分:0)
您的陈述“任何数量的线程都可以进入synchronized
块”是错误的。
理论上,如果一个线程位于synchronized
块中,则这将阻止其他线程进入。对于IntentService
,这是不可能的,因为IntentService
使用单个工作线程来处理工作量。
调用wait()
是线程同步方法,而不是延迟方法。这与调用sleep()
不同,后者仅在特定时间段内阻塞线程。当您调用wait()
时,它将阻塞线程,直到另一个线程调用notify()
,该线程用于协调多个线程之间的活动。 wait(10000)
阻塞线程,直到从另一个线程调用notify()
为止,或者直到超时到期(在这种情况下为10秒)。因此,看起来应该在某个地方有另一个线程正在调用notify()
对象上的IntentService
来唤醒它。
使用notify()
和wait()
会带来额外的复杂性。为了调用这些方法中的任何一个,必须首先获得对象监视器的锁定(通过使用synchronized
)。这意味着对wait()
和notify()
的调用必须在对象上synchronized
的{{1}}块内或synchronized
方法内。
调用synchronized
的线程实际上释放了对象上的锁。这意味着该线程在wait()
块/方法内被阻止,但是在等待时该对象没有锁定。一旦synchronized
被调用(或超时已过期),线程将重新获得对象上的锁并继续执行。
有关在Java中使用notify()
和notify()
的更多信息,请搜索这些术语并进行阅读。
如果应该做的只是延迟10秒,然后向logcat写入内容,那么该代码将非常复杂。您可以只调用wait()
而不是sleep()
来调用wait()
语句。但是,正如另一位发布者所指出的那样,如果经常调用此synchronized
,则会造成积压,因为对Service
的每次调用都会延迟10秒,并且由于只有一个工作线程,所有呼叫均已序列化。例如:在10:00:00调用onHandleIntent()
,logcat中的条目将在10:00:10出现。如果在10:00:01再次调用startService()
,则该条目将在10:00:20之前不会出现在日志中,因为第二个对startService()
的调用要到10:00才会发生:10。