我试图了解Java(和JVM)如何在后台创建线程。
我在实践中阅读了Java并发性,但是找不到关于默认情况下所有Java应用程序是单线程还是多线程的很好的解释。
一方面,从开发人员的角度来看:我编写了一系列顺序代码,而没有创建Thread实例或在任何地方实现Runnable。我是否需要同步任何内容?我应该确保类是线程安全的吗?如果是这样,我应该停止使用具有可变字段的POJO吗?我读到JVM将为自己的业务在后台创建多个线程。 JVM是否还在创建线程来运行我的应用程序而无需我显式创建那些线程?
另一方面:我编写了一堆代码,在其中明确创建了Threads和Runnable实现。 JVM是否会剥离自己的线程来“帮助”我的多线程代码运行得更快?
我完全没有想到以正确的方式考虑JVM的线程处理。但是,我是一名入门级Java开发人员,但我讨厌让我感到困惑。
答案 0 :(得分:3)
一方面,从开发人员的角度来看:我编写了一系列顺序代码,而没有创建Thread实例或实现 可在任何地方运行。我是否需要同步任何内容?我可以做 确保我的类是线程安全的?如果是这样,我应该停止吗 使用具有可变字段的POJO?
直接的答案是:不,您不需要主动使对象成为线程安全的,以保护它们免受未创建的线程的并发访问。
通常来说,除非您自己做一些已知的事情来创建线程,然后组织起来共享一个线程,否则不会创建与您编写的代码和类 1 并发交互的线程。线程之间的对象实例。创建Thread
对象是创建线程的一个示例,但还有其他示例。这是一个非详尽的清单:
Executor
或ExecutorService
实现使用线程(大多数)。Stream
方法,例如,通过parallelStream
方法创建流。因此,线程通常不会突然弹出,而是由于您执行了某些操作。即使库创建了您不知道的线程,也不必担心,因为除非另有说明,否则它们将不会访问您的对象,或者将使用锁定来确保它们以序列化的方式访问它们(或库严重损坏)。
因此,除非您知道正在使用线程的地方,否则通常无需担心跨线程同步。因此,默认情况下,您无需使对象成为线程安全的。
1 我对“与您编写的代码进行交互”进行区分,因为典型的JVM将在幕后使用多个线程,即使您从未创建任何线程,也可以执行诸如垃圾之类的家政任务集合,调用终结器,监听JMX连接,等等。
答案 1 :(得分:0)
您编写的应用代码是单线程还是多线程?除非您明确采取措施来创建新线程-例如通过执行类似 A B C replace
1: 1 11 21 1
2: 2 12 22 2
3: 3 13 23 3
4: 4 14 24 4
5: 5 15 25 5
6: 6 16 26 16
7: 7 17 27 17
8: 8 18 28 18
9: 9 19 29 29
10: 10 20 30 30
的操作-您的应用程序代码将是单线程的。
在单个JVM中运行多个线程吗?是的,总是如此–后台会运行各种与您编写的代码无关的事情(例如垃圾收集器)。
您应防止并发问题吗?使用单线程应用程序,则不需要。但是,如果您的代码本身创建了一个(或多个)线程,或者如果您的代码以某种方式打包以供其他应用程序创建者使用(也许您已经创建了供其他人在其代码中使用的数据结构),则您可能需要采取措施以确保并发正确性。在创建供他人使用的代码的情况下,最好在Javadoc中声明您的代码不是线程安全的。例如,Thread t = new Thread();
(https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html)说“请注意,此实现未同步” 以及建议的解决方法。