多线程的应用(一)

本文围绕Java多线程展开,介绍了实现多线程的方式,如继承Thread类、实现Runnable接口等。阐述了多线程的实际应用场景,如文件跑批。还讲解了Java线程的生命周期、启动原理,以及不建议用stop命令,而应使用interrupt方法优雅终止线程。

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

线程的应用

如何应用多线程
在 Java 中,有多种方式来实现多线程。继承 Thread 类、
实现 Runnable 接口、使用 ExecutorService、Callable、
Future 实现带返回结果的多线程。
一.继承 Thread 类创建线程
Thread 类本质上是实现了 Runnable 接口的一个实例,代
表一个线程的实例。启动线程的唯一方法就是通过 Thread
类的 start()实例方法。start()方法是一个 native 方法,它会
启动一个新线程,并执行 run()方法。这种方式实现多线程
很简单,通过自己的类直接 extend Thread,并复写 run()
方法,就可以启动新线程并执行自己定义的 run()方法。

public class MyThread extends Thread {
 public void run() {
 System.out.println("MyThread.run()");
 }
}
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start(); 
myThread2.start();

**二.实现 Runnable 接口创建线程 **
如果自己的类已经 extends 另一个类,就无法直接 extends
Thread,此时,可以实现一个 Runnable 接口

public class MyThread extends OtherClass implements
Runnable {
 public void run() {
 System.out.println("MyThread.run()");
 }
} 

**三.实现 Callable 接口通过 FutureTask 包装器来创建 Thread 线程 **
有的时候,我们可能需要让一步执行的线程在执行完成以
后,提供一个返回值给到当前的主线程,主线程需要依赖
这个值进行后续的逻辑处理,那么这个时候,就需要用到
带返回值的线程了。Java 中提供了这样的实现方式

public class CallableDemo implements Callable<String> {
 public static void main(String[] args) throws
ExecutionException, InterruptedException {
 ExecutorService executorService=Executors.newFixedThreadPool(1);
 CallableDemo callableDemo=new CallableDemo();
 Future<String> future=executorService.submit(callableDemo);
 System.out.println(future.get());
 executorService.shutdown();
 }
 @Override
 public String call() throws Exception {
 int a=1;
 int b=2;
 System.out.println(a+b);
 return "执行结果:"+(a+b);
 }
}

多线程的实际应用场景

其实大家在工作中应该很少有场景能够应用多线程了,因
为基于业务开发来说,很多使用异步的场景我们都通过分
布式消息队列来做了。但并不是说多线程就不会被用到,
你们如果有看一些框架的源码,会发现线程的使用无处不

之前我应用得比较多的场景是在做文件跑批,每天会有一
些比如收益文件、对账文件,我们会有一个定时任务去拿
到数据然后通过线程去处理

Java 并发编程的基础

基本应用搞清楚以后,我们再来基于Java线程的基础切入,
来逐步去深入挖掘线程的整体模型。
Java 线程既然能够创建,那么也势必会被销毁,所以线程
是存在生命周期的,那么我们接下来从线程的生命周期开
始去了解线程。
线程的生命周期
线程一共有 6 种状态(NEW、RUNNABLE、BLOCKED、
WAITING、TIME_WAITING、TERMINATED)
NEW:初始状态,线程被构建,但是还没有调用 start 方法
RUNNABLED:运行状态,JAVA 线程把操作系统中的就绪
和运行两种状态统一称为“运行中”
BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程
因为某种原因放弃了 CPU 使用权,阻塞也分为几种情况
➢ 等待阻塞:运行的线程执行 wait 方法,jvm 会把当前
线程放入到等待队列
➢ 同步阻塞:运行的线程在获取对象的同步锁时,若该同
步锁被其他线程锁占用了,那么 jvm 会把当前的线程
放入到锁池中
➢ 其他阻塞:运行的线程执行 Thread.sleep 或者 t.join 方
法,或者发出了 I/O 请求时,JVM 会把当前线程设置
为阻塞状态,当 sleep 结束、join 线程终止、io 处理完
毕则线程恢复
TIME_WAITING:超时等待状态,超时以后自动返回
TERMINATED:终止状态,表示当前线程执行完毕.
在这里插入图片描述
显示线程的状态
➢ 运行该示例,打开终端或者命令提示符,键入“jps”,
(JDK1.5 提供的一个显示当前所有 java 进程 pid 的命
令)
➢ 根据上一步骤获得的 pid,继续输入 jstack pid(jstack
是 java 虚拟机自带的一种堆栈跟踪工具。jstack 用于
打印出给定的 java 进程 ID 或 core file 或远程调试服
务的 Java 堆栈信息)
通过上面的分析,我们了解到了线程的生命周期,现在在
整个生命周期中并不是固定的处于某个状态,而是随着代
码的执行在不同的状态之间进行切换
线程的启动
前面我们通过一些案例演示了线程的启动,也就是调用
start()方法去启动一个线程,当 run 方法中的代码执行完毕
以后,线程的生命周期也将终止。调用 start 方法的语义是
当前线程告诉 JVM,启动调用 start 方法的线程。
线程的启动原理
很多同学最早学习线程的时候会比较疑惑,启动一个线程
为什么是调用 start 方法,而不是 run 方法,这做一个简单
的分析,先简单看一下 start 方法的定义
在这里插入图片描述
start 方法中有一个函数调用:实际就是调用平台创建线程的方法来创建线程。 os::start_thread(thread);,调用平台启动线程的方法,最终会调用 Thread.cpp 文件中的 JavaThread::run()方法.(此处省略了具体.cpp文件查看过程)

线程的终止

线程的启动过程大家都非常熟悉,但是如何终止一个线程
呢? 这是面试过程中针对 3 年左右的人喜欢问到的一个
题目。
线程的终止,并不是简单的调用 stop 命令去。虽然 api 仍
然可以调用,但是和其他的线程控制方法如 suspend、
resume 一样都是过期了的不建议使用,就拿 stop 来说,
stop 方法在结束一个线程时并不会保证线程的资源正常释
放,因此会导致程序可能出现一些不确定的状态。
要优雅的去中断一个线程,在线程中提供了一个 interrupt
方法
interrupt 方法
当其他线程通过调用当前线程的 interrupt 方法,表示向当
前线程打个招呼,告诉他可以中断线程的执行了,至于什
么时候中断,取决于当前线程自己。
线程通过检查资深是否被中断来进行相应,可以通过
isInterrupted()来判断是否被中断。通过 interrupt,设置了一个标识告诉线程
可 以 终 止 了 , 线 程 中 还 提 供 了 静 态 方 法
Thread.interrupted()对设置中断标识的线程复位。比如在
上面的案例中,外面的线程调用 thread.interrupt 来设置中
断标识,而在线程里面,又通过 Thread.interrupted 把线
程的标识又进行了复位

public class InterruptDemo {
 private static int i;
 public static void
main(String[] args) throws
InterruptedException {
 Thread thread=new
Thread(()->{
 while(true){
 
if(Thread.currentThread().isInterrupted()){

System.out.println("before:"+Thread.currentThread().isInterrupted())
;
Thread.interrupted(); //对线程进行复
位,由 true 变成 false
System.out.println("after:"+Thread.currentThread().isInterrupted());
 }
 }
 },"interruptDemo");
 thread.start();
 TimeUnit.SECONDS.sleep(1);
 thread.interrupt();
 }
}

为什么要复位
Thread.interrupted()是属于当前线程的,是当前线程对外
界中断信号的一个响应,表示自己已经得到了中断信号,
但不会立刻中断自己,具体什么时候中断由自己决定,让
外界知道在自身中断前,他的中断状态仍然是 false,这就
是复位的原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值