news 2026/7/15 2:23:00

Java多线程入门:创建与结束线程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java多线程入门:创建与结束线程

第十七章:多线程

常见概念

进程和线程

进程:运行中的程序

线程:线程是由进程创建的,是进程的一个实体,当然线程也可以由线程创建,如:一个线程创建一个子线程

单线程和多线程

单线程:同一个时刻,只允许执行一个线程 多线程:同一个时刻,可以执行多个线程

并发和并行

并发:同一个时刻,多个任务交替执行(单核来回切换) 并行:同一个时刻,多个任务同时执行。多核CPU可以实现并行 并发和并行可以同时存在:并行中又包含并发

同步进而实现互斥

线程 / 进程的同步和互斥:

  • 同步:协调多个并发实体执行的顺序 —进而实现—>互斥:控制多个并发实体不能同时访问同一个资源,即要上锁

多线程

创建线程⭐

实现Runnable接口,重写run方法:

packagecom.lcz.mutithread.create;/** * @author lcz * @version 1.0 */publicclassThread02{publicstaticvoidmain(String[]args){Dogdog=newDog();Threadthread=newThread(dog);thread.start();}}classDogimplementsRunnable{privateintcount=0;@Overridepublicvoidrun(){while(true){System.out.println("小狗汪汪汪叫..."+(++count));try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}if(count==8){break;}}}}

结束线程⭐

  1. 自动结束:线程完成任务后,自动结束
  2. 通知结束:使用布尔变量来控制任务的结束,进而线程结束
packagecom.lcz.mutithread.exit;/** * @author lcz * @version 1.0 */publicclassExit01{publicstaticvoidmain(String[]args){Dogdog=newDog();Threadthread=newThread(dog);thread.start();try{Thread.sleep(10*1000);//主线程休眠10秒}catch(InterruptedExceptione){thrownewRuntimeException(e);}dog.setLoop(false);//通知退出子线程}}classDogimplementsRunnable{privateintcount=0;privatebooleanloop=true;publicvoidsetLoop(booleanloop){this.loop=loop;}@Overridepublicvoidrun(){while(loop){System.out.println("小狗汪汪汪叫..."+(++count));try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}if(count==80){break;}}}}

线程常用方法

  • setName
  • getName
  • setPriority
  • getPriority
  • sleep:静态方法
  • interrupt
  • yield(静态方法):线程的礼让,让出cpu,让其他线程执行,但不一定成功(取决于内核态资源是否紧张)
  • join:线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程所有的任务
细节
1.线程优先级的范围: MAX_PRIORITY:10MIN_PRIORITY:1NORM_PRIORITY:52.interrupt,中断线程,但并没有真正的结束线程,所以一般用于中断正在休眠线程3.sleep:使当前线程休眠
代码演示
packagecom.lcz.mutithread.method;/** * @author lcz * @version 1.0 * 线程常用方法使用 */publicclassMethod{publicstaticvoidmain(String[]args){Dogdog=newDog();Threadthread=newThread(dog);thread.setName("lcz");thread.setPriority(Thread.NORM_PRIORITY);thread.start();for(inti=0;i<5;i++){System.out.println("主线程:"+i+",线程名字:"+thread.getName()+",线程优先级:"+thread.getPriority());try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException();}}thread.interrupt();//中断thread线程休眠}}classDogimplementsRunnable{privateintcount=0;@Overridepublicvoidrun(){while(true){System.out.println("小狗汪汪汪叫..."+(++count));try{Thread.sleep(20000);}catch(InterruptedExceptione){}if(count==50)break;}}}
packagecom.lcz.mutithread.method;/** * @author lcz * @version 1.0 * 线程常用方法:yield和join */publicclassMethod01{publicstaticvoidmain(String[]args)throwsInterruptedException{Tt=newT();Threadthread=newThread(t);thread.start();for(inti=0;i<20;i++){System.out.println("主线程(小弟)吃包子"+i);Thread.sleep(1000);if(i==5){//thread.join();//子线程插队Thread.yield();}}}}classTimplementsRunnable{privateintcount=0;@Overridepublicvoidrun(){while(true){System.out.println("子线程(老大)吃包子 "+(++count));try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}if(count==20)break;}}}

用户线程和守护线程

  1. 用户线程:也叫工作线程,当线程的任务执行完或通知方式来结束
  2. 守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束
    1. 常见的守护线程:垃圾回收机制
    2. thread.setDaemon(true); //将子线程设置为守护线程,会随着用户线程(工作线程)结束而自动结束
packagecom.lcz.mutithread.method;/** * @author lcz * @version 1.0 */publicclassMyDaemonThread{publicstaticvoidmain(String[]args)throwsInterruptedException{Aa=newA();Threadthread=newThread(a);thread.setDaemon(true);//将子线程设置为守护线程,会随着用户线程(工作线程)结束而自动结束//守护线程作用:用于检测其他线程信息thread.start();for(inti=0;i<10;i++){System.out.println("框框学习..."+i);Thread.sleep(500);}}}classAimplementsRunnable{@Overridepublicvoidrun(){while(true){for(inti=0;i<10;i++){System.out.println("嗷嗷难受..."+i);try{Thread.sleep(500);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}}}}

线程状态⭐

线程生命周期:

1.new:创建状态 2.Runnable:可运行状态 (1):Ready:就绪状态 (2):Running:运行状态 4.waiting:等待状态,等待某些资源 5.Blocked:阻塞状态,等待互斥锁 6.Terminated:终止状态

线程同步互斥机制⭐

synchronized 关键字声明方法为同步方法 / 代码块为同步代码块,即仅能一个线程访问,访问时会为这个方法上一个互斥锁,进而实现线程互斥

同步的局限性:导致程序的执行效率降低

publicsynchronizedvoidm(Stringname){//需要被同步的代码}synchronized(this){//使用 this 对象互斥锁,保证任一时刻,只能有一个线程访问该对象//同步代码块:得到对象互斥锁的线程才可执行同步代码块}
解决超卖问题
packagecom.lcz.mutithread.syn_;/** * @author lcz * @version 1.0 */publicclassSellTicket01extendsThread{privatestaticintcount=100;publicsynchronizedstaticvoidsell(){//将静态方法声明为同步方法,锁为当前类 SellTicket01.class//表示只有获得该锁,才可执行下方同步代码while(true){if(count<=0)break;try{Thread.sleep(50);}catch(InterruptedExceptione){thrownewRuntimeException(e);}System.out.println("售票一张,剩余票数:"+(--count));}}@Overridepublicvoidrun(){sell();}publicstaticvoidmain(String[]args){//不会出现超卖现象,因为使用线程同步机制实现线程互斥SellTicket01sellTicket01=newSellTicket01();SellTicket01sellTicket02=newSellTicket01();SellTicket01sellTicket03=newSellTicket01();sellTicket01.start();sellTicket02.start();sellTicket03.start();}}

死锁现象⭐

两个线程相互占有对方资源,而想要获取对方已占有资源,但无法获得对方资源就无法释放自身资源的情况!编写程序要避免。

packagecom.lcz.mutithread.syn_;/** * @author lcz * @version 1.0 */publicclassDeadLock{publicstaticvoidmain(String[]args){MyDeadLockDemomyDeadLockDemo=newMyDeadLockDemo(true);ThreadA=newThread(myDeadLockDemo);A.setName("A线程");MyDeadLockDemomyDeadLockDemo1=newMyDeadLockDemo(false);ThreadB=newThread(myDeadLockDemo1);B.setName("B线程");A.start();B.start();}}classMyDeadLockDemoimplementsRunnable{privatebooleanflag;privatestaticObjecto1=newObject();privatestaticObjecto2=newObject();publicMyDeadLockDemo(booleanflag){this.flag=flag;}@Overridepublicvoidrun(){if(flag){synchronized(o1){System.out.println("当前线程: "+Thread.currentThread().getName());synchronized(o2){System.out.println("当前线程: "+Thread.currentThread().getName());}}}else{synchronized(o2){System.out.println("当前线程: "+Thread.currentThread().getName());synchronized(o1){System.out.println("当前线程: "+Thread.currentThread().getName());}}}}}
是否释放锁的几种情况

会释放锁:

  • 线程进入等待状态(等待某些资源),会释放锁

不会释放锁:

  • sleep()和 yield()方法,不会释放锁

更多编程学习资源

编程学习公众号【程序员论周】

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 8:02:24

体验Yolo-v5省钱攻略:云端GPU按需付费,比买显卡省万元

体验Yolo-v5省钱攻略&#xff1a;云端GPU按需付费&#xff0c;比买显卡省万元 你是不是也遇到过这样的情况&#xff1a;作为一名自由设计师&#xff0c;平时主要做视觉创意、UI设计或品牌包装&#xff0c;偶尔需要处理一些图像识别任务——比如从大量素材中自动检测人物姿态、…

作者头像 李华
网站建设 2026/7/1 21:51:30

RPCS3模拟器完全攻略:从零开始畅玩PS3游戏大作

RPCS3模拟器完全攻略&#xff1a;从零开始畅玩PS3游戏大作 【免费下载链接】rpcs3 PS3 emulator/debugger 项目地址: https://gitcode.com/GitHub_Trending/rp/rpcs3 想要在PC上重温经典PS3游戏&#xff1f;RPCS3模拟器是你的最佳选择&#xff01;作为目前最强大的PlayS…

作者头像 李华
网站建设 2026/7/1 23:03:06

Page Assist终极指南:浏览器侧边栏无缝对话本地AI模型

Page Assist终极指南&#xff1a;浏览器侧边栏无缝对话本地AI模型 【免费下载链接】page-assist Use your locally running AI models to assist you in your web browsing 项目地址: https://gitcode.com/GitHub_Trending/pa/page-assist 你是否厌倦了依赖云端AI服务时…

作者头像 李华
网站建设 2026/7/4 10:50:09

Qwen vs Llama3轻量模型实战对比:CPU部署效率全面评测

Qwen vs Llama3轻量模型实战对比&#xff1a;CPU部署效率全面评测 1. 背景与选型动机 随着边缘计算和本地化AI服务的兴起&#xff0c;轻量级大语言模型在资源受限环境下的部署能力变得愈发重要。尤其是在缺乏GPU支持的场景中&#xff0c;如嵌入式设备、低配服务器或开发测试环…

作者头像 李华
网站建设 2026/7/6 14:35:33

图解三极管内部载流子运动:通俗解释其导通原理

三极管是怎么“导通”的&#xff1f;一张图看懂内部电子的“长征”之路你有没有想过&#xff0c;一个比指甲盖还小的三极管&#xff0c;为什么能用微弱的电流控制大功率设备&#xff1f;为什么它既能放大信号&#xff0c;又能当开关使用&#xff1f;答案藏在它的“肚子”里——…

作者头像 李华
网站建设 2026/7/6 1:31:58

DeepSeek-R1-Distill-Qwen-1.5B多任务处理:并行推理优化

DeepSeek-R1-Distill-Qwen-1.5B多任务处理&#xff1a;并行推理优化 1. 引言 1.1 业务场景描述 在当前AI应用快速落地的背景下&#xff0c;轻量级大模型的高效部署成为中小型服务和边缘计算场景的关键需求。DeepSeek-R1-Distill-Qwen-1.5B 是基于 Qwen-1.5B 模型&#xff0c…

作者头像 李华