Daemon Threads in Java – Java中的守护线程

最后修改: 2017年 10月 31日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this short article, we’ll have a look at daemon threads in Java and see what can they be used for. We’ll also explain the difference between daemon threads and user threads.

在这篇短文中,我们将看看Java中的守护线程,看看它们可以用来做什么。我们还将解释守护线程和用户线程之间的区别。

2. Difference Between Daemon and User Threads

2.守护线程和用户线程的区别

Java offers two types of threads: user threads and daemon threads.

Java提供两种类型的线程:用户线程和守护线程。

User threads are high-priority threads. The JVM will wait for any user thread to complete its task before terminating it.

用户线程是高优先级的线程。JVM将等待任何用户线程完成其任务后再终止它。

On the other hand, daemon threads are low-priority threads whose only role is to provide services to user threads.

另一方面,守护线程是低优先级的线程,其唯一作用是为用户线程提供服务。

Since daemon threads are meant to serve user threads and are only needed while user threads are running, they won’t prevent the JVM from exiting once all user threads have finished their execution.

由于守护线程是为用户线程服务的,只有在用户线程运行时才需要,所以一旦所有用户线程执行完毕,它们就不会阻止JVM退出。

That’s why infinite loops, which typically exist in daemon threads, will not cause problems, because any code, including the finally blocks, won’t be executed once all user threads have finished their execution. For this reason, daemon threads are not recommended for I/O tasks.

这就是为什么通常存在于守护线程中的无限循环不会造成问题,因为任何代码,包括finally块,一旦所有用户线程完成执行,就不会被执行。出于这个原因,不建议将守护线程用于I/O任务。

However, there’re exceptions to this rule. Poorly designed code in daemon threads can prevent the JVM from exiting. For example, calling Thread.join() on a running daemon thread can block the shutdown of the application.

然而,这条规则也有例外。守护线程中设计不良的代码可以阻止JVM退出。例如,在运行中的守护线程上调用Thread.join()可以阻止应用程序的关闭。

3. Uses of Daemon Threads

3.守护线程的用途

Daemon threads are useful for background supporting tasks such as garbage collection, releasing memory of unused objects and removing unwanted entries from the cache. Most of the JVM threads are daemon threads.

守护线程对于后台支持任务非常有用,例如垃圾收集、释放未使用对象的内存以及从缓存中删除不需要的条目。大部分的JVM线程都是守护线程。

4. Creating a Daemon Thread

4.创建一个守护神线程

To set a thread to be a daemon thread, all we need to do is to call Thread.setDaemon(). In this example, we’ll use the NewThread class which extends the Thread class:

要将一个线程设置为守护线程,我们所需要做的就是调用Thread.setDaemon()。在这个例子中,我们将使用NewThread类,它扩展了Thread类。

NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();

Any thread inherits the daemon status of the thread that created it. Since the main thread is a user thread, any thread that is created inside the main method is by default a user thread.

任何线程都会继承创建它的线程的守护状态。由于主线程是一个用户线程,任何在main方法中创建的线程都默认为一个用户线程。

The method setDaemon() can only be called after the Thread object has been created and the thread has not been started. An attempt to call setDaemon() while a thread is running will throw an IllegalThreadStateException:

方法setDaemon()只能在Thread对象被创建且线程未被启动之后被调用。如果试图在线程运行时调用setDaemon(),将抛出IllegalThreadStateException

@Test(expected = IllegalThreadStateException.class)
public void whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
    NewThread daemonThread = new NewThread();
    daemonThread.start();
    daemonThread.setDaemon(true);
}

5. Checking if a Thread Is a Daemon Thread

5.检查一个线程是否是守护线程

Finally, to check if a thread is a daemon thread, we can simply call the method isDaemon():

最后,要检查一个线程是否是守护线程,我们可以简单地调用方法isDaemon()

@Test
public void whenCallIsDaemon_thenCorrect() {
    NewThread daemonThread = new NewThread();
    NewThread userThread = new NewThread();
    daemonThread.setDaemon(true);
    daemonThread.start();
    userThread.start();
    
    assertTrue(daemonThread.isDaemon());
    assertFalse(userThread.isDaemon());
}

6. Conclusion

6.结论

In this quick tutorial, we’ve seen what daemon threads are and what they can be used for in a few practical scenarios.

在这个快速教程中,我们已经看到了什么是守护线程,以及它们在一些实际场景中可以用来做什么。

As always, the full version of the code is available over on GitHub.

一如既往,完整版本的代码可在GitHub上获得