java 中的线程模型和线程池
原文合集地址如下,有需要的朋友可以关注
Java 中的线程池
Java 中是实现线程模型的方式
在 Java 中,线程模型是通过 Java 线程库和 Java 虚拟机(JVM)的支持来实现的。Java 提供了一种简单而强大的多线程编程模型,允许开发者创建和管理线程,实现并发执行的能力。
Java 中线程模型的实现主要包括以下几个关键概念和机制:
Thread 类:Java 中的线程是通过 Thread 类表示的。开发者可以通过继承 Thread 类或实现 Runnable 接口来创建自己的线程。通过重写 Thread 类的 run()方法或在 Runnable 接口的实现类中实现 run()方法,可以定义线程要执行的代码逻辑。
线程状态:Java 线程可以处于多个状态,如新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和终止(Terminated)等状态。线程的状态会随着线程的执行和调度而变化。
线程调度:Java 的线程调度由 JVM 负责,它决定了线程的执行顺序和优先级。线程调度可以是抢占式的,即高优先级的线程会抢占 CPU 资源执行;也可以是协同式的,即线程自己主动让出 CPU 资源。通过设置线程的优先级可以影响线程的调度顺序。
同步机制:在多线程编程中,线程访问共享资源时可能会出现竞态条件(Race Condition)和数据不一致等问题。Java 提供了多种同步机制,如 synchronized 关键字、Lock 接口及其实现类、volatile 关键字等,用于控制多个线程之间的同步访问,确保线程安全。
线程间通信:多个线程之间可能需要进行通信和协调。Java 提供了一些机制来实现线程间的通信,如 wait()和 notify()方法、Condition 接口及其实现类、阻塞队列等。这些机制允许线程等待特定条件的发生,并在条件满足时进行通知。
线程组:Java 中的线程可以组织成线程组,以方便对一组线程进行管理和控制。线程组可以统一设置线程的优先级、处理未捕获异常等。
Java 中实现线程池的方式
在 Java 中,有几个与线程池相关的类可以使用。以下是其中一些主要的类:
Executor
:是一个接口,定义了执行任务的方法。ExecutorService
:也是一个接口,扩展了Executor
接口,并提供了更多管理和控制线程池的方法,比如提交任务、关闭线程池等。Executors
:是一个实用类,提供了创建各种类型线程池的静态工厂方法。ThreadPoolExecutor
:是一个可扩展的线程池实现类,实现了ExecutorService
接口,用于管理和执行多线程任务。ScheduledExecutorService
:继承自ExecutorService
接口,支持在指定的延迟时间后执行任务,或者以固定的时间间隔周期性执行任务。ScheduledThreadPoolExecutor
:是ThreadPoolExecutor
的子类,实现了ScheduledExecutorService
接口,用于创建定时任务线程池。
这些类提供了丰富的功能和选项来管理线程池,提交任务,并控制任务的执行方式和调度。通过使用这些类,可以更好地利用多线程来处理并发任务。
Executor
和 ExecutorService
定义了哪些行为
Executor
接口和ExecutorService
接口定义了用于执行任务的方法,其中包括以下动作:
Executor
接口定义了一个单独的方法:
void execute(Runnable command)
: 接受一个Runnable
任务,并在将来的某个时间执行该任务。
ExecutorService
接口继承了Executor
接口,并扩展了更多管理和控制线程池的方法,包括:
void shutdown()
: 平缓关闭线程池,等待所有已提交的任务执行完成后关闭。List<Runnable> shutdownNow()
: 立即关闭线程池,尝试停止所有正在执行的任务,并返回未执行的任务列表。boolean isShutdown()
: 判断线程池是否已经关闭。boolean isTerminated()
: 判断线程池中所有任务是否已经执行完成。boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
: 阻塞当前线程,直到线程池中的所有任务执行完成或者达到指定的超时时间。Future<?> submit(Runnable task)
: 提交一个Runnable
任务给线程池执行,并返回一个Future
对象,可以用于获取任务的执行结果。Future<T> submit(Runnable task, T result)
: 提交一个Runnable
任务给线程池执行,并返回一个带有结果值的Future
对象。Future<T> submit(Callable<T> task)
: 提交一个Callable
任务给线程池执行,并返回一个Future
对象,可以用于获取任务的执行结果。<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
: 执行给定的任务集合,并返回表示任务结果的Future
列表。该方法会阻塞直到所有任务执行完成。<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
: 执行给定的任务集合,并返回其中一个任务的结果。一旦有任务成功执行并返回结果,其他未完成的任务将被取消。void execute(Runnable command)
: 接受一个Runnable
任务,并在将来的某个时间执行该任务。
这些方法提供了对线程池的管理、任务提交和任务执行结果获取的功能。通过使用ExecutorService
接口的实现类,可以更好地控制和管理多线程任务的执行。
Executors
类提供了创建哪些线程池的方法
Executors
类提供了以下方法用于创建不同类型的线程池:
1. newSingleThreadExecutor()
创建一个包含单个线程的线程池,用于执行任务。任务会按照提交的顺序依次执行。
2. newSingleThreadExecutor(ThreadFactory threadFactory)
创建一个包含单个线程的线程池,并可以指定线程的工厂来创建线程。
我们直接在 newFixedThreadPool()方法中使用 Lambda 表达式定义了 ThreadFactory 的实现。Lambda 表达式接受一个 Runnable 对象并返回一个 Thread 对象,这样就实现了 ThreadFactory 接口的 newThread()方法。在 Lambda 表达式的主体中,我们创建了一个新的线程对象,并对其进行自定义设置,然后返回该线程。
3. newFixedThreadPool(int nThreads)
创建一个固定大小的线程池,线程池中的线程数量固定为nThreads
。
4. newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
创建一个固定大小的线程池,并可以指定线程的工厂来创建线程。下面是一个简单的使用例子:
5. newCachedThreadPool()
创建一个可以根据需要自动调整线程数量的线程池。线程池会根据任务的数量动态地创建和回收线程。
6. newCachedThreadPool(ThreadFactory threadFactory)
创建一个可以根据需要自动调整线程数量的线程池,并可以指定线程的工厂来创建线程。
7. newSingleThreadScheduledExecutor()
创建一个包含单个线程的定时执行任务的线程池。
8. newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
创建一个包含单个线程的定时执行任务的线程池,并可以指定线程的工厂来创建线程。
9. newScheduledThreadPool(int corePoolSize)
创建一个固定大小的定时执行任务的线程池。
10. newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
创建一个固定大小的定时执行任务的线程池,并可以指定线程的工厂来创建线程。
11. newWorkStealingPool()
创建一个工作窃取线程池,线程数量根据系统的处理能力而定。
12. newWorkStealingPool(int parallelism)
创建一个指定并行度的工作窃取线程池。
创建好线程池之后如何使用
创建好线程池之后,将得到 ExecutorService,这时根据 ExecutorService 提供的方法,,你可以使用它来提交任务并管理线程池的执行。以下是一些常见的方法和用法:
提交任务并获得
Future
对象:使用submit()
方法来提交一个Runnable
或Callable
任务,并获得一个Future
对象,用于获取任务执行的结果或监控任务的状态。
执行任务并忽略结果:使用
execute()
方法来提交一个Runnable
任务,并忽略其返回结果。
关闭线程池:使用
shutdown()
方法来平缓地关闭线程池,该方法将允许已提交的任务执行完成,但不接受新的任务提交。
强制关闭线程池:使用
shutdownNow()
方法来立即关闭线程池,该方法将尝试终止正在执行的任务,并返回等待执行的任务列表。
等待所有任务完成:使用
awaitTermination()
方法来阻塞当前线程,直到所有任务完成或超时。
通过这些方法,你可以向线程池提交任务并控制线程池的生命周期。请根据具体的需求选择适当的方法来管理和使用 ExecutorService
对象。
评论