Java 多线程 与 线程池

本文详细介绍了Java中的多线程概念,包括线程生命周期、创建线程的三种方法、实现接口与继承Thread的比较。重点讨论了线程池的使用,如ExecutorService、Executors和ThreadPoolExecutor,以及如何向线程池提交任务和关闭线程池。此外,还讲解了FutureTask及其在异步计算中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Java 中线程的生命周期

该java.lang.Thread的类包含一个静态枚举-它定义了它的潜在状态。在任何给定的时间点,线程只能处于以下状态之一:

  • NEW:新创建的线程尚未启动执行
  • RUNNABLE:运行或准备执行,但它正在等待资源分配
  • BLOCKED:等待获取监视器锁定以进入或重新进入同步块/方法
  • WAITING:等待其他一些线程执行特定操作,没有任何时间限制
  • TIMED_WAITING:等待某个其他线程在指定时间段内执行特定操作
  • TERMINATED:已完成执行

2. 创建 Java 线程的三种方法

  • 第一种是创建 Thread 子类的一个实例并重写 run 方法
  • 第二种是实现 Runnable 接口
  • 第三种是实现 Callable 接口

实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。

3. 实现接口 VS 继承 Thread

实现接口会更好一些,因为:

  • Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
  • 类可能只要求可执行就行,继承整个 Thread 类开销过大。

4. Runable 和 Callable 的比较

  • 与 Runnable 相比,Callable 可以有返回值,返回值通过 Future 进行封装。
  • 由于 Runable 的 run() 方法没有指定“throws”子句,因此无法传播进一步检查的异常;
    Callable的call()方法包含“throws Exception”子句,因此我们可以轻松地进一步传播已检查的异常.。

5. 使用线程池

线程池模式有助于节省多线程应用程序中的资源,还可以在某些预定义的限制内包含并行性。

使用线程池时,以并行任务的形式编写并发代码,并将它们提交给线程池的实例执行。此实例控制多个重用线程以执行这些任务。

合理使用线程池能带来 3 个好处:

  • 降低资源消耗
  • 提高响应速度
  • 提高线程的可管理性

下面再介绍下线程池的运行状态. 线程池一共有五种状态, 分别是:

  • RUNNING :能接受新提交的任务,并且也能处理阻塞队列中的任务;

  • SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态。(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);

  • STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;

  • TIDYING:如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。

  • TERMINATED:在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。

    进入TERMINATED的条件如下:

    • 线程池不是RUNNING状态;
    • 线程池状态不是TIDYING状态或TERMINATED状态;
    • 如果线程池状态是SHUTDOWN并且workerQueue为空;
    • workerCount为0;
    • 设置TIDYING状态成功。
5.1 Executors, Executor and ExecutorService
  1. Executor接口: 它是 Executor 框架的基础,只提供了一个execute() 方法,用于执行提交的 Runnable 实例
  2. ExecutorService 接口:继承了 Executor 接口,包含了大量的方法控制任务的进度和管理服务的终止。使用此接口,您可以提交要执行的任务,还可以使用返回的Future实例控制其执行。
  3. Executors 类:包含了创建预先配置的线程池实例的几种方法
5.2 实例化线程池

ThreadPoolExecutor主要有三种线程池:

  • FixedThreadPool:所有任务只能使用固定大小的线程,适用于负载比较重的服务器
  • SingleThreadExecutor:只有当前线程挂了之后才能创建新的线程,相当于大小为 1 的FixedThreadPool。
  • CachedThreadPool:一个任务创建一个线程,没有大小限制。
1. Executors 类的工厂方法

创建ExecutorService的最简单方法是使用Executors类的工厂方法之一

ExecutorService executor = Executors.newFixedThreadPool(10);
2. 直接创建线程池

因为ExecutorService是一个接口,所以可以使用其任何实现的实例。在java.util.concurrent包中有几种实现可供选择,或者可以创建自己的实现。

ExecutorService executorService = 
  new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,   
  new LinkedBlockingQueue<Runnable>());
5.3 向线程池提交任务

有两个方法可以完成这个事,分别为execute()和 submit()。

1. execute()

用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功,executor()方法输入的任务是一个Runnable 实例。

 executorService.execute(() -> System.out.println("executed..."));
2. submit()

用于提交需要返回值的任务,线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功,还可以通过调用 Future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,其重载版本get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这个时候有可能任务还没有完成。

Future<Integer> future = executorService.submit(() -> Arrays.asList(1, 52, 836, 52).stream()
                .mapToInt(i -> i)
                .sum());
System.out.println("the result of Callable: " + future.get());
5.4 关闭线程池

可以通过调用线程池的 shutdown 或 shutdownNow 方法来关闭线程池。他们的原理是遍历线程池中的工作线程,然后逐个调用线程的 interrupt 方法来中断线程,所以无法响应的线程永远无法终止。

1.shutdown()

通常放在execute后面。如果调用 了这个方法,一方面,将线程池的状态设置为 SHUTDOWN 状态,表明当前线程池已不再接收新添加的线程,新添加的线程会被拒绝执行。另一方面,中断所有没有在执行任务的线程,当所有线程执行完毕时,回收线程池的资源。注意,它不会马上关闭线程池!

2. shutdownNow()

首先将线程池的状态设置 STOP 状态, 不管当前有没有线程在执行,马上关闭线程池,并返回等待执行任务的列表,这个方法要小心使用,要不可能会引起系统数据异常!

6. FutureTask

Future 接口及其实现类 FutureTask 代表异步计算的结果

6.1 FutureTask 简介

FutureTask 除了实现Future接口之外,还实现了 Runnable 接口。

6.2 FutureTask 的使用
  • FutureTask 可以交给 Executor 执行
  • 通过 ExecutorService.submit(…) 方法返回一个 FutureTask
  • FutureTask 可以由调用线程直接执行(FutureTask.run())。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值