在同步块中使用 wait()

Using wait() inside a synchronized block

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

    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 置于阻塞状态。这与调用 wait()Thread 相同吗? 基本上,当我将文本传递给 Service 时,我希望 Service 等待 10 秒,然后在 LogCat 中显示消息。 我从来没有用过 wait() 所以有人可以向我解释上面的代码在做什么吗?

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

以上代码将用于将日志条目延迟 10 秒。但是,IntentService 只有 1 个工作线程,因此如果连续请求每 10 秒出现一次以上,就会积压。

因为只涉及1个工作线程,所以使用同步确实是错误的答案。为什么不放弃 IntentService,而只在 UI 线程上使用 CountDownTimer?

执行所有这些操作
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,创建并行执行的 外观 ,而无需多线程的复杂性。

你的说法 "any number of threads can enter the synchronized block" 是错误的。

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

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

此处使用 notify()wait() 会带来额外的复杂性。为了调用这些方法中的任何一个,必须首先获得对象监视器上的锁(通过使用 synchronized)。这意味着对 wait()notify() 的调用必须在 synchronized 块内或在 synchronized 对象上的 synchronized 方法内。

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

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


如果这段代码只是延迟 10 秒,然后向 logcat 写入内容,那么这段代码相当复杂。您可以只调用 sleep() 而不是 wait(),这不需要 synchronized 语句。然而,正如另一位发帖人指出的那样,如果经常调用此 Service,这将造成积压,因为每次调用 onHandleIntent() 都会延迟 10 秒,并且由于只有 1 个工作线程,所有调用都是序列化的。示例:在 10:00:00 调用 startService(),logcat 中的条目将出现在 10:00:10。如果在 10:00:01 再次调用 startService(),该条目将不会出现在 logcat 中,直到 10:00:20,因为不会发生对 onHandleIntent() 的第二次调用直到 10:00:10.