当前位置: 首页 > news >正文

多线程经典问

1.1 线程和进程的区别?

进程是正在运行的程序实例,也是资源分配的基本单位;线程是进程中的执行单元,是 CPU 调度的基本单位。

不同进程之间内存隔离,同一进程内的线程共享堆、方法区等资源,但每个线程有自己的栈和程序计数器。

线程比进程更轻量,上下文切换成本更低。

1.2 并行和并发有什么区别?

并发:一个CPU核心交替执行多个线程

并行:多个CPU核心各自执行自己的线程

1.3 创建线程的四种方式

在java中一共有四种常见的创建方式,分别是:继承Thread类、实现runnable接口、实现Callable接口、线程池创建线程。通常情况下,我们项目中都会采用线程池的方式创建线程。

1.4 runnable 和 callable 有什么区别?

  1. Runnable 接口run方法没有返回值;Callable接口call方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

  2. Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞当前调用 get() 的线程

  3. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛

1.5 线程的 run()和 start()有什么区别?

核心区别->run里是啥,start是啥->run的另一种情况->run重复 start一次

run()start()最大的区别是:start()才是真正启动一个新线程,直接调用run()只是普通方法调用。

run()里面放的是线程要执行的业务逻辑。如果我们调用thread.start(),JVM 会创建一个新的线程,让这个新线程在被 CPU 调度后去执行run()方法。

但如果直接调用thread.run(),它不会创建新线程,而是在当前线程里同步执行,就和调用一个普通方法一样。

另外,同一个线程对象的start()只能调用一次,重复调用会抛IllegalThreadStateException;但run()作为普通方法可以被多次调用。

1.6 线程包括哪些状态,状态之间是如何变化的?

JDK 里线程状态在Thread.State里定义了 6 种:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。

一个线程刚创建、还没调用start()的时候是 NEW;调用start()之后进入 RUNNABLE。这里的 RUNNABLE 不一定代表正在执行,也可能是在等 CPU 调度。线程的run()方法执行完之后,就进入 TERMINATED。

如果线程在进入synchronized代码块时竞争锁失败,会进入 BLOCKED,等锁释放后再重新竞争,竞争到锁后回到可运行状态。

如果线程调用wait()join()这类方法,会进入 WAITING;如果调用sleep(long)wait(long)join(long),会进入 TIMED_WAITING。区别是wait()会释放锁,需要 notify 或 notifyAll 唤醒后再重新竞争锁;而sleep()只是让线程睡一段时间,不会释放锁。

1.7 新建 T1、T2、T3 三个线程,如何保证它们按顺序执行?

可以用join()join()表示当前线程等待目标线程执行完。

在主线程里先t1.start(),然后t1.join();等 T1 完成后再t2.start()t2.join();最后启动 T3。这样就能保证 T1、T2、T3 按顺序执行。

1.8 notify()和 notifyAll()有什么区别?

notifyAll:唤醒所有wait的线程
notify:只随机唤醒一个 wait 线程

1.9 在 java 中 wait 和 sleep 方法的不同?

wait()sleep()都能让当前线程暂时不执行,都会让出 CPU,也都可以被interrupt()打断。

主要区别有三个。第一,方法归属不一样,sleep()Thread的静态方法,wait()Object的方法。

第二,锁的行为不一样。sleep()不要求先拿锁,如果它在synchronized里执行,也不会释放锁;而wait()必须在同步代码块里调用,也就是必须先拿到对象锁,并且调用后会释放这个锁。

第三,唤醒方式不一样。sleep(long)时间到了就会进入可运行状态;wait()需要被notify()notifyAll()唤醒,wait(long)也可以超时醒。不过wait()被唤醒后不是马上执行,还要重新竞争锁。

所以简单说,sleep()更像是线程自己暂停一下,wait()更像是线程之间配合通信。

1.10 如何停止一个正在运行的线程?

Java 里不推荐用stop()停线程,因为它会强制终止,可能导致锁和共享数据状态不一致。

推荐做法是让线程自己退出,比如用volatile标志位控制循环,或者调用interrupt()设置中断标记。

interrupt()不是直接停止线程,如果线程在sleep/wait/join中会抛InterruptedException;如果线程正常运行,就需要自己检查isInterrupted()后退出。

http://www.cnnetsun.cn/news/2908219.html

相关文章:

  • 【Android】瞬净ins版-无水印解析-无水印视频保存
  • 【Android】myReader电子书阅读器-一键扫描阅读小说
  • 3个常见误区:为什么你的网络压力测试总是失败?
  • 评测全网10款主流降AI率平台:只选真正管用的那一款!
  • MC68SZ328 DragonBall Super VZ:经典嵌入式SoC的架构解析与实战设计
  • Synology HDD db:群晖NAS硬盘兼容性终极解决方案
  • OmicVerse实战指南:高效多组学分析的5大核心优势
  • 从文字到视觉:5分钟掌握Flowchart Fun的智能流程图创作技巧
  • Python进阶:从执行模型与对象机制理解真实Bug根源
  • 成功的大数据治理项目须坚持“六个导向”和“三个相结合”
  • 新手必看:用eNSP模拟真实网络,手把手教你搞定BGP跨AS通信(含路由黑洞排查)
  • 从Arduino到树莓派:手把手教你玩转UART、IIC、SPI通信(附Python/C++代码示例)
  • 冥想第一千九百零九天
  • MC9S08QE128内存管理与寄存器映射实战:从原理到高效嵌入式开发
  • 符合消防专项要求玻璃防火门多场景合规落地应用研究摘要
  • MC68341定时器与QSPI模块深度解析:从寄存器原理到实战调试
  • 腾讯AI,有自己的坐标
  • 如何打造终极iOS漫画阅读体验:E-Hentai Viewer完全指南 [特殊字符]
  • yolov26改进 | 损失函数改进篇 | 最新ShapeIoU、InnerShapeIoU损失助力细节涨点(含三十余种损失函数改进方法)
  • 3步掌握d2s-editor:零基础玩转暗黑破坏神2存档修改
  • 如何快速掌握AI图层分离:5步提升设计效率的完整指南
  • 什么是 supremum pseudo-record?
  • FLEXPART模式实战:如何用后向轨迹分析锁定污染源(附Python后处理脚本)
  • 别再手动PS了!用Python+OpenCV给论文配图加局部放大镜,5分钟搞定
  • 第1章:架构基础
  • 如何免费获取抖音无水印高清视频:douyin-downloader完整指南
  • 生产级机器学习系统:防御性设计与系统性风险治理
  • 从零样本到思维分支:LLM推理增强的工业级落地路径
  • Docker分层构建缓存原理详解:零基础快速吃透镜像加速机制
  • MCU模拟比较器与DAC实战:低功耗监控与自动波形生成