java - 在同步块(synchronized block)内使用 wait()

标签 java android concurrency android-service java-threads

我偶然发现 Android Service 类中的一段代码,其中有一个带有 wait 语句的同步块(synchronized block)。 代码如下:

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

最佳答案

你的说法“任意数量的线程都可以进入synchronized block ”是错误的。

理论上,如果一个线程位于 synchronized block 内,则会阻止其他线程进入。对于 IntentService 来说这是不可能的,因为 IntentService 使用单个工作线程来处理工作负载。

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

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

调用wait()的线程实际上释放了对象上的锁。这意味着线程被阻塞在同步 block /方法内,但它在等待时没有对象上的锁。一旦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(),则该条目直到 10:00:20 才会出现在 logcat 中,因为第二次调用 onHandleIntent() 直到 10:00:10 才会发生。

关于java - 在同步块(synchronized block)内使用 wait(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52844416/

相关文章:

java - 致命异常 : AsyncTask #1

Java JPA - 从在第二次运行时不起作用的实体创建表

android - 如何让 Toasts 仅在应用程序位于前台时才出现?

java - CompletableFuture 和 CountDownLatch 超时

java - 泛型: token 语法错误 "extends", , 预期

java - 如何告诉 Spring 在不提供构造函数参数的情况下实例化选定的 bean?

android - gradle.属性。未使用的属性(property)

android widget listview 可点击

C++多进程?

java - 我想以某种方式添加延迟,单击按钮更新标签, hibernate 几秒钟,然后更新其他标签