版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章
多线程目录CONTENTS01线程概述02线程的创建03线程的生命周期及状态转换04线程的调度05多线程同步0606综合实训案例线程概述0110.1.1进程与线程01进程的定义进程是程序的一次执行过程,是系统资源分配的基本单位,拥有独立的内存空间,多个进程间相互独立。02线程的定义线程是进程中的一个执行流程,是CPU调度的基本单位,共享进程的内存空间,多个线程间可以高效通信。10.1.1进程与线程进程与线程对比分析对比项目进程线程资源分配独立分配资源共享进程资源通信方式进程间通信(IPC)共享变量、方法调用切换开销大(上下文切换代价高)小(切换效率更高)稳定性互不影响一个线程出错可能影响其他线程并发能力较弱强,适合高并发处理10.1.2多线程的优势与应用场景多线程的优势多线程可以提高CPU利用率,改善程序响应性,充分利用多核处理器,简化复杂任务模型。典型应用场景多线程广泛应用于图形用户界面程序、网络服务器、文件下载、游戏开发和数据处理等领域。线程的创建0210.2.1继承Thread类创建线程实现步骤代码示例特点限制//自定义线程类,继承ThreadpublicclassMyThreadextendsThread{//重写run()方法,定义线程的任务publicvoidrun(){for(inti=0;i<5;i++){//输出当前线程的名称和循环变量System.out.println(Thread.currentThread().getName()+"执行中:"+i);}}publicstaticvoidmain(String[]args){//创建两个线程对象MyThreadt1=newMyThread();
MyThreadt2=newMyThread();
//启动线程,注意不要使用run()t1.start();t2.start();}}10.2.2实现Runnable接口创建线程实现步骤代码示例特点限制//自定义任务类,实现Runnable接口publicclassMyRunnableimplementsRunnable{publicvoidrun(){for(inti=0;i<5;i++){//输出当前线程的名称和循环变量System.out.println(Thread.currentThread().getName()+"执行中:"+i);}}publicstaticvoidmain(String[]args){//创建Runnable实例Runnabler=newMyRunnable();//将Runnable对象封装到Thread对象中
Threadt1=newThread(r);Threadt2=newThread(r);//启动线程t1.start();t2.start();}}线程的生命周期及状态转换0310.3.1线程状态定义状态英文中文描述说明NEW新建状态线程被创建,但未调用
start()方法RUNNABLE就绪状态线程已启动,等待
CPU分配时间片RUNNING(无枚举)运行状态虽未单独列出,但线程实际运行时处于该状态BLOCKED阻塞状态等待获取锁资源(如进入同步代码块被阻塞)WAITING等待状态无限期等待其他线程通知(如调用
wait())TIMED_WAITING计时等待状态等待指定时间后自动唤醒(如调用
sleep()、join(1000))TERMINATED终止状态线程执行完毕或被异常终止10.3.2线程启动与状态转换(1)新建状态(NEW):通过newThread()创建线程对象后,线程处于新建状态,此时线程只是一个普通的Java对象,尚未与操作系统的线程资源关联。(2)可运行状态(RUNNABLE):调用start()方法后,线程进入可运行状态,此时JVM为线程分配了必要的系统资源,线程等待CPU时间片调度。(3)计时等待状态(TIMED_WAITING):主线程通过Thread.sleep(100)短暂休眠,确保子线程执行到sleep(1000)语句,子线程执行sleep(1000)后进入计时等待状态,在指定时间内不会消耗CPU资源。(4)终止状态(TERMINATED):t.join()方法使主线程等待子线程执行完毕,子线程完成run()方法中的所有代码后进入终止状态。10.3.2线程启动与状态转换实现步骤代码示例特点限制publicclassThreadStateDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{//创建线程,任务是休眠1秒Threadt=newThread(()->{try{Thread.sleep(1000);//进入TIMED_WAITING}catch(InterruptedExceptione){e.printStackTrace();}});System.out.println("状态1:"+t.getState());//NEWt.start();System.out.println("状态2:"+t.getState());//RUNNABLEThread.sleep(100);//主线程暂停,以便子线程进入TIMED_WAITINGSystem.out.println("状态3:"+t.getState());//TIMED_WAITINGt.join();//等待线程执行结束System.out.println("状态4:"+t.getState());//TERMINATED}}线程的调度0410.4.1线程的优先级优先级范围每个线程都拥有一个优先级,Java中的优先级为一个整数值,范围从1(Thread.MIN_PRIORITY)到10(Thread.MAX_PRIORITY),默认值为5(Thread.NORM_PRIORITY)。平台差异线程优先级只是对调度器的提示,具体调度策略由操作系统决定,不同平台可能有所不同。10.4.2线程休眠线程休眠是通过Thread.sleep(longmillis)方法实现的,让当前线程暂停执行指定的毫秒数,让出CPU给其他线程。publicclassSleepDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{System.out.print("3...");Thread.sleep(1000);System.out.print("2...");Thread.sleep(1000);System.out.print("1...");}}10.4.3线程让步Thread.yield()方法会使当前线程主动让出CPU,让系统重新调度线程。它不会阻塞线程,只是把当前线程放回就绪队列中,有可能马上又被调度回来。publicclassYieldDemo{publicstaticvoidmain(String[]args){Runnabletask=()->{for(inti=0;i<3;i++){System.out.println(Thread.currentThread().getName()+"执行中");Thread.yield();//提示调度器切换线程}};newThread(task,"线程A").start();newThread(task,"线程B").start();}}10.4.4线程插队join()方法可以使一个线程等待另一个线程执行完成。主线程调用子线程的join(),表示“插队”,直到子线程执行完毕,主线程才继续执行。publicclassJoinDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{System.out.println("子线程开始");try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("子线程结束");});t.start();t.join();//主线程等待t结束System.out.println("主线程继续");}}多线程同步05多线程同步概述线程安全问题在多线程程序中,多线程并发执行带来更高的程序效率和更强的响应能力,但也伴随着资源访问冲突的问题。多个线程对共享数据或资源的非同步访问,可能导致数据错误、状态不一致甚至程序崩溃。这些问题被统称为线程安全问题。原子性与可见性线程安全问题的根源在于操作非原子性和内存可见性问题,synchronized关键字可以解决这些问题。10.5.1线程安全问题当多个线程并发访问共享变量,并且至少有一个线程修改了该变量,而该变量的访问又没有采取同步机制控制时,就可能出现线程安全问题,导致运行结果不可预测。publicclassUnsafeBank{privatestaticintbalance=100;publicstaticvoidmain(String[]args){Runnabletask=()->{for(inti=0;i<5;i++){if(balance>0){System.out.println(Thread.currentThread().getName()+"取出10元");balance-=10;System.out.println("余额:"+balance);}}};newThread(task,"用户A").start();newThread(task,"用户B").start();}}10.5.2同步代码块synchronized是Java提供的最基本同步机制。它可以修饰代码块,表示该段代码在同一时刻只能由一个线程执行。使用synchronized关键字修饰的代码块可以实现同步。publicclassSafeBank{privatestaticintbalance=100;privatestaticfinalObjectlock=newObject();publicstaticvoidmain(String[]args){Runnabletask=()->{for(inti=0;i<5;i++){synchronized(lock){if(balance>0){System.out.println(Thread.currentThread().getName()+"取出10元");balance-=10;System.out.println("余额:"+balance);}}}};newThread(task,"用户A").start();newThread(task,"用户B").start();}}10.5.3同步方法如果多个线程访问同一个对象的某个方法,可以将该方法声明为synchronized实现同步。synchronized还可以修饰方法,称为同步方法。该方法在执行时会自动对当前对象加锁(实例方法)或类加锁(静态方法)。publicclassCounter{privateintcount=0;publicsynchronizedvoidincrement(){count++;}publicsynchronizedintgetCount(){returncount;}}10.5.4死锁问题死锁是指两个或多个线程在执行过程中,因争夺资源而造成互相等待、无法继续执行的现象。publicclassDeadlockDemo{privatestaticfinalObjectA=newObject();privatestaticfinalObjectB=newObject();publicstaticvoidmain(String[]args){Threadt1=newThread(()->{synchronized(A){System.out.println("线程1持有A,等待B...");synchronized(B){System.out.println("线程1获得B");}}});Threadt2=newThread(()->{synchronized(B){System.out.println("线程2持有B,等待A...");synchronized(A){System.out.println("线程2获得A");}}});t1.start();t2.start();}}10.5.4死锁问题—死锁产生的四个必要条件01互斥条件一个资源一次只能被一个线程占用。02不可剥夺线程获得的资源在使用完之前不能被强制释放。03请求与保持线程持有资源的同时,申请其他资源。04循环等待两个或多个线程形成一种头尾相接的等待资源的环路。10.5.4死锁问题—避免死锁的常见策略01统一资源申请顺序,破坏“循环等待”条件;02避免嵌套锁;03使用tryLock()等机制设置超时时间;04引入资源调度器统一管理锁申请。综合实训案例06综合实训1:生产者消费者问题——案例需求通过一个缓冲区作为共享资源,实现一个生产者线程不断“生产数据”,消费者线程不断“消费数据”,并通过wait()和notify()方法实现线程之间的通信与同步。(1)生产者负责生成商品,如果缓冲区满,则等待消费者消费后继续生产;(2)消费者从缓冲区中取出商品,如果缓冲区空,则等待生产者生产后继续消费;(3)需要线程安全地控制对缓冲区的读写访问。综合实训1:生产者消费者问题——实现思路(1)使用synchronized实现同步控制;(2)使用wait()阻塞线程,释放锁;(3)使用notify()唤醒等待的线程;(4)使用标志变量或容器判断生产与消费条件。综合实训1:生产者消费者问题——代码实现classStore{privateintproduct=0;//当前库存publicsynchronizedvoidproduce(){while(product>=1){//缓冲区已满,不能生产try{wait();//释放锁并等待}catch(InterruptedExceptione){e.printStackTrace();}}product++;System.out.println(Thread.currentThread().getName()+"生产了一个产品,库存:"+product);notify();//唤醒消费者线程}publicsynchronizedvoidconsume(){while(product==0){//缓冲区为空,不能消费try{wait();}catch(InterruptedExceptione){e.printStackTrace();}}product--;System.out.println(Thread.currentThread().getName()+"消费了一个产品,库存:"+product);notify();//唤醒生产者线程}}综合实训1:生产者消费者问题——代码实现publicclassProducerConsumerDemo{publicstaticvoidmain(String[]args){Storestore=newStore();//生产者线程Runnableproducer=()->{for(inti=0;i<10;i++){duce();}};//消费者线程Runnableconsumer=()->{for(inti=0;i<10;i++){store.consume();}};newThread(producer,"生产者").start();newThread(consumer,"消费者").start();}}综合实训1:生产者消费者问题——运行结果综合实训2:定时任务调度——案例需求(1)避免频繁创建销毁线程所带来的系统资源浪费;(2)控制最大并发线程数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 国际化展览项目管理-第1篇-洞察与解读
- 应激反应与舒张压的关系探究-洞察与解读
- 感冒止咳糖浆的吸收与血药峰分析-洞察与解读
- 2026年湖北公开遴选公务员考试(行政执法类)经典试题及答案
- 2026年广西住房城乡建设领域施工现场专业人员岗位考试(资料员)训练题及答案
- 2026年福建住建系统行政执法资格专业考试仿真试题及答案
- 2026公开遴选和公开选调公务员考试(综合知识)考前冲刺试题及答案
- 2025年物业管理师职业技能鉴定考试(理论知识高级、三级)题库及答案无锡
- 2025年全国招标采购专业技能大赛(央企组)冲刺试题及答案
- 2026及未来5年中国多股丝电极行业发展研究报告
- 2026兰州城市学院招聘事业编制专职辅导员10人笔试模拟试题及答案详解
- 2026江苏宿迁经开区古楚街道城管辅助人员招聘4人笔试模拟试题及答案详解
- 2026-2030中国文化旅游行业市场深度调研及战略规划与投资前景研究报告
- 新版电力重大事故隐患判定标准及治理监督管理规定解读
- 2025-2026学年鲁教版(新教材)小学信息技术五年级下册(全册)教学设计(附目录p112)
- 阿达木单抗在非银屑病炎症性皮肤病治疗中的应用专家共识解读
- 建筑企业安全奖惩制度
- 电仪修班组安全职责培训课件
- 代理记账公司内部复核制度
- 2026年黑龙江哈尔滨市文化广电和旅游局“丁香人才周”(春季)事业单位引才招聘24人易考易错模拟试题(共500题)试卷后附参考答案
- 2025年国有企业招聘招商专业人才20人笔试历年难易错考点试卷带答案解析
评论
0/150
提交评论