- 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加
- 915. Partition Array into Disjoint Intervals 分割数组
- 932. Beautiful Array 漂亮数组
- 940. Distinct Subsequences II 不同的子序列 II
本文我们将讲解 Java 中的线程池 ( Thread Pool ),从 Java 标准库中的线程池的不同实现开始,到 Google 开发的 Guava 库的前世今生。
本章节涉及到很多前几个章节中阐述的知识点。我们希望你是按照顺序阅读下来的,不然有些知识会一头雾水。
Java 语言的实现中,把 Java 线程一一映射到操作系统级的线程,而后者是操作系统的资源,这意味着,如果开发者毫无节制地创建线程,那么线程资源就会被快速的耗尽。
在Windows 操作系统上,每个线程要预留出 1m 的内存空间,意味着 2G 的内存理论上做多只能创建 2048 个线程。而在 Linux 上,最大线程数由常量 PTHREAD_THREADS_MAX 决定,一般为 1024。
出于模拟并行性的目的,Java 线程之间的上下文切换也由操作系统完成。因为线程上下文切换需要消耗时间,所以,一个简单的观点是:产生的线程越多,每个线程花在实际工作上的时间就越少。
为什么会有线程上下文切换?
一台电脑,运行起来后,它的 CPU 是固定的,05 年之前,还是单核时代,也就是一次只能运行一个线程,虽然随着时间的推移,现在的 CPU 已经有很多个核心,比如 8 核 16 核之类的。但相比于一个应用程序能够创建的线程数,那真的是太少了。而每个核心一次只能运行一个线程,所以多个线程需要运行时就需要来回不停的在多个线程间切换,这就是线程之间的上下文切换。
为了节制创建线程的数量,也为了节省创建线程的开销,因此提出了线程池的概念。线程池模式有助于节省多线程应用程序中的资源,还可以在某些预定义的限制内包含并行性。
当我们使用线程池时,我们可以以并行任务的形式编写并发代码并将其提交到线程池的实例中执行。
这个线程池实例控制了多个重用线程以执行这些任务。
这种线程池模式,允许我们控制应用程序创建的线程数,生命周期,以及计划任务的执行并将传入的任务保留在队列中。
Executors 是一个帮助类,提供了创建几种预配置线程池实例的方法。如果你不需要应用任何自定义的微调,可以调用这些方法创建默认配置的线程池,因为它能节省很多时间和代码。
Executor 和 ExecutorService 接口则用于与 Java 中不同线程池的实现协同工作。通常,你应该将代码与线程池的实际实现分离,并在整个应用程序中使用这些接口。
Executor 接口提供了一个 execute() 方法将 Runnable 实例提交到线程池中执行。
下面的代码是一个快速示例,演示了如何使用 Executors API 获取包含了单个线程池和无限队列支持的 Executor 实例,以便按顺序执行任务。
Executor executor = Executors.newSingleThreadExecutor();
获取了Executor 示例后,我们就可以使用 execute() 方法将一个只在屏幕上打印 Hello World 的任务提交到队列中执行。
executor.execute(() -> System.out.println("Hello World"));
上面这个示例使用了 lambda ( Java 8特性 )提交任务,JVM 会自动推断该任务为 Runnable
我们在Java Shell 演示下上面的代码
jshell> import java.util.concurrent.*
jshell> Executor executor = Executors.newSingleThreadExecutor();
executor ==> java.util.concurrent.Executors$FinalizableDelegatedExecutorService@1e127982
jshell> executor.execute(() -> System.out.println("Hello World"));
jshell> Hello World
jshell>
ExecutorService 接口则包含大量用于控制任务进度和管理服务终止的方法。我们可以使用此接口来提交要执行的任务,还可以使用此接口返回的 Future 实例控制任务的执行。
下面的示例中,我们创建了一个 ExecutorService 的实例,提交了一个任务,然后使用返回的 Future 的 get() 方法等待提交的任务完成并返回值。
ExecutorService executorService = Executors.newFixedThreadPool(10);
Future<String> future = executorService.submit(() -> "Hello World");
// 一些其它操作
String result = future.get();
在实际使用时,我们并不会立即调用 future.get() 方法,可能会等待一些时间,推迟调用它直到我们需要它的值用于计算等目的。
ExecutorService 中的 submit() 方法被重载为支持 Runnable 或 Callable ,它们都是功能接口,可以接收一个 lambdas 作为参数( 从 Java 8 开始 ):
如果想让编译器将参数推断为 Callable 类型,只需要 lambda 返回一个值即可。
ExecutorService 接口的更多使用范例和特性,你可以访问前面的章节 一文秒懂 Java ExecutorService。
完成此任务的最佳方法是什么:主线程(线程 A)创建另外两个线程(线程 B 和线程 C)。线程 B 和 C 执行繁重的磁盘 I/O,最终需要将它们创建的资源传递给线程 A,然后调用外部 DLL 文件中的
我是一名对 Julia 语言感兴趣的新手程序员。文档( https://docs.julialang.org/en/v1/base/multi-threading/ )说 Threads.@threa
python中的thread.start_new_thread和threading.Thread.start有什么区别? 我注意到,当调用 start_new_thread 时,新线程会在调用线程终止
我正在学习安卓蓝牙编程。我从 Google 的 Android 开发者网站上复制了大部分代码以供学习。这个想法是监听服务器上的连接是在一个新线程中完成的,而不会阻塞 UI 线程。当收到连接请求时,连接
执行对象方法的线程是否依赖于创建它的线程上的线程? 假设您的 java 应用程序中有两个线程 Thread1 和 Thread2,以及两个类 ClassA 和 ClassB。 您在 Thread1 上
我正在用这段代码测试 C++11 线程,但是在创建线程时,我遇到了错误没有匹配函数调用 'std::thread::thread()'. 这就像我给 std::thread ctr 的函数有什么问题,
我有如下类 eventEngine 和网关: class eventEngine { public: eventEngine(); std::thread threa; std
我需要运行与列表 dirlist 中的元素一样多的 Observer 类线程。当我运行它 python 控制台时,它可以正常工作。 class Observer(Thread): def ru
我在一本 Java 书中读到了下面的代码。我知道主类默认继承 Thread 类,所以 currentThread();而不是 Thread.currentThread();也会做这项工作。 但我不明白
我在我的系统中使用第 3 方 API,该 API 启动一个永久运行的用户线程。一旦我的程序结束,JVM 由于该线程而继续运行,因此我尝试获取此线程引用并通过更改它 thread.setDaemon(t
我所知道的 Python 中的每个对象都可以通过调用来处理其基类初始化: super(BaseClass, self).__init__() threading.Thread 的子类似乎不是这种情况,
在我最近从事的 Xamarin 项目中,我可以看到开发人员使用了 Java.Lang.Thread 以及 System.Threading.Thread(用于非常相似的操作 - 例如在后台加载数据)。
我在 Julia 中运行双循环。代码非常简单。 w = rand(1000,1000) function regular_demo(w::Array{Float64, 2}) n = size
我在 Windows 上使用 Python 3。我正在使用 threading.Thread动态运行一个函数,我可以带参数或不带参数调用它。我正在设置一个列表,其中的第一项是定义路径的字符串。其他参数
我遇到了一些使用线程模块(使用 Python 2.6)管理线程的示例。 我想了解的是这个例子是如何调用“运行”方法的,在哪里调用的。我在任何地方都看不到它。 ThreadUrl 类在 main() 函
假设我从 threading.Thread 派生: from threading import Thread class Worker(Thread): def start(self):
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
使用 WinDbg 和 SOS,我有以下内容: 0:011> !threads ThreadCount: 7 UnstartedThread: 0 BackgroundThread: 4 Pendin
App Engine 给出错误: com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfe
我正在尝试将 Swing JEditorPane 嵌入到 JavaFX 项目中,如下代码所示。 Platform.runLater(() -> { SyntaxTester ob = new
我是一名优秀的程序员,十分优秀!