版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java多线程Java
Java
多线程处理机制线程的生命周期创建线程的方法线程同步线程联合
…
守护线程
本章内容提要
…0在程序设计中,经常会遇到多个任务同时执行的情况,这种资源被交替占用的任务执行
过程,被称为多线程处理,其中,每个任务一
次动态执行过程被称为进程。进程执行过程中
的暂停被称为中断。进程通过中断被分解成了
若干段,每一段被称为一个线程。10.1Java多线程处理机制在Java语言的运行环境中(JVM),
内
置了一个线程调度器,用于确定某一时刻由哪一
个线程占用计算机资源进行执行,从而实现了
多线程操作。当Java程序开始运行时
,main()
方法首先执行,此时线程调度器会开启一个线
程,即为主线程
(Java
Applet的主线程是Web
浏览器)
,
负
责main()方法的执行,除主线程
之外的线程被称为其它线程。10.1Java多线程处理机制10.2线程的生命周期Java线程从最初的创建直至最后执行的结束,需要遵循一个生命周期。利用生命周期,使得线程更加容易被分析和控制。线程的生命周期分为四个阶段一新建、运行、中断、死亡。转换过程如下图:新建
入队
等待队列
出队
运行执行结束中断解除
导致中断中断
死亡图10.1线程生命周期线程对象定义后,线程直接进入新建状态。处于
新建状态的线程不占用计算机资源。2.
运行当线程占用计算机资源时,就进入了运行状态。
线程由新建状态转入运行状态并不是直接完成的,需
要进入一个由进程调度器控制的等待队列,等待计算
机资源的闲置(被其它线程释放),当计算机资源闲
置时
,依据队列的先进先出性,最先进入等待队列的
线程最先出队,获得计算机资源,转入运行状态。10.2线程的生命周期1.新建3.
中
断处于运行状态的线程必须在运行一段时间后让出计算机资源,这就是线程的中断。中断
原因包括:》阻
塞》线程调度器的控制》通过sleep(long
mill)方法》通过wait()方法10.2线程的生命周期当线程中断解除时(例如:通过Scanner类的方法输入了数据、经
过mill
毫秒后休眠结束),线
程并不会立刻返回运行状态,而是重新进入等待队
列进行排队,并依据队列先进先出的使用原则,占
用计算机资源,进入运行状态。4
.
死亡线程执行完毕后,就进入了最后的死亡状态,
线程的生命周期同时结束。10.2线程的生命周期Java
多线程的实现是通过创建线程对象开始的。线程对象的创建有两种方法一利用Thread类的子类创建线程和使用Runnable接口创建线程。两种方法相比,第一种较为简单,
第二种更加灵活。10.3创建线程的方法1.利用Thread
类的子类创建线程Thread类位于java.lang
包中,是Java语
言提供的线程类。定义一个继承Thread类的
子类,在该类中重写Thread类中的publicvoid
run()方法,当子类对象一线程对象获
得资源时,会调用run()方法,执行线程操作。10.3创建线程的方法10.3创建线程的方法例10-1classSimpleThreadextendsThread{
publicvoidrun(){Sysntln(getName()+i);sleep((int)(Math.random()*1000));}catch(InterruptedExceptione){Sysntln(e);Sysntln("DONE!"+getName());for(int
i=0;i<3;i++){try{class
Example10_1{public
static
void
main(String
args[){SimpleThreadone=newSimpleThread();
one.setName("oneThread");one.start();SimpleThreadtwo=newSimpleThread();
two.setName("twoThread");two.start();10.3创建线程的方法2.使用Runnable接口对象创建线程利用Thread类定义直接线程对象,此时,调用
的Thread类的构造方法需要设置一个对象做参数,
而定义该对象的类必须实现jRunnable接口,这个
对象被称为线程对象的目标对象。Runnable接口中
定义了public
void
run()方法,定义目标对象的
类使用了Runnable接口,必须重写其中的publicvoidrun()方法。10.3创建线程的方法例10-2import
jDate;importjGraphics;publicclass
Example10_2extendsjApplet
implements
Runnable{ThreadclockThread;publicvoidstart(){if(clockThread==null){clockThread=newThread(this,"Clock");
clockThread.start();10.3创建线程的方法publicvoid
run(){while(clockThread
I=null){int();clockThread.sleep(1000);}catch(InterruptedExceptioneSysntln(e);tryrep10.3创建线程的方法publicvoidpaint(Graphicsg){
Date
now=new
Date();g.drawString(now.toString(),5,10);public
void
stop({clockThread.stop();clockThread=null;10.3创建线程的方法10.3创建线程的方法3.线程常用操作方法public
void
start()使线程进入等待队列public
void
run()使线程进入运行状态public
boolean
isAlive()判断线程是否处于运行状态public
static
void
sleep(long
mill)使正在运行的线程休眠(中断)mill
毫秒publicstaticThreadcurrentThread()获取正在运行的线程对象public
void
interrupt()吵醒正在休眠的线程10.3创建线程的方法■例10-3■publicclassThreadMethodimplements
Runnable{
Thread
liLei,fire
,alarm;■
ThreadMethod(){liLei=new
Thread(this);public
void
run(){long
time=0;while(true){if(Thread.currentThread()==liLei)Sysntln("李雷今天太累了,抽着烟睡着了
……
.");try{fire
=new
Thread(this);fire.start();Thread.sleep(1000*60*60);}catch(InterruptedException
e){Sysntln("
李雷被报警声叫醒了!");errupt();return;}else
if(Thread.currentThread()==fire){if(time==0){Sysntln("
李雷的烟头点燃了地毯,李雷还在睡10.3创建线程的方法try{fire
=new
Thread(this);fire.start();Thread.sleep(1000*60*60);}catch(InterruptedException
e){Sysntln("
李雷被报警声叫醒了!");
errupt();return;}else
if(Thread.currentThread()==fire){
if(time==0){Sysntln("
李雷的烟头点燃了地毯,李雷还在睡10.3创建线程的方法10.3创建线程的方法time=2000;try{Thread.sleep(time);}catch(InterruptedExceptione){Sysntln(e);}else
if(time>0&&time<3000){Sysntln("地毯着火了,李雷还没醒!!!");
time=4000;try{Thread.sleep(time);}catch(InterruptedExceptione){Sysntln(e);}else
if(time>3000){Sysntln("
火势越来越大……");alarm=new
Thread(this);alarm.start();try{Thread.sleep(time);}catch(InterruptedExceptione){Sysntln("扑灭了地毯上的火,吸烟真是危险啊!");return;}else
if(Thread.currentThread()==alarm){Sysntln("报警器被触发啦!");10.3创建线程的方法10.3创建线程的方法Thread.sleep(500);
}catch(InterruptedExceptione)Sysntln(e);liLerrupt();return;class
Example10_3{publicstaticvoidmain(String)args{ThreadMethodmethod=newThreadMethod();metrt();try{■4.多线程中的共享与独享当多个线程使用同一个目标对象时,它们都
将利用目标对象所属类中重写的run()方法进行线程
的执行。此时,如果run()
方法中使用了类中的成员
变量,那么该成员变量的操作对每个线程都是开放
的一目标对象的成员变量被多个线程的访问共享。但是,对于run()方法中定义的局部变量,由于其是
在每个线程调用run()
方法时被分配内存空间,调
用
结束后又立即释放内存空间,因此仅被每个线程的
访问独享。10.3创建线程的方法class
SavingBox
implements
Runnable{double
balance;publicvoid
run(){int
count=0;while(true){balance=balance+1000;count++;try{Sysntln(Thread.currentThread().getName()+"第"+count+”次存钱,存钱盒目前有"+balance+"元。");if(count==3){Sysntln(Thread.currentThread().getName()+存了"+count+"次,本月存钱结束。");10.3创建线程的方法Thread.sleep(2000);}catch(InterruptedExceptione){Sysntln(e);}}public
class
Example10_4{public
static
void
main(String[]args)SavingBoxbox=newSavingBox();Thread
liLei=newThread(box);liLei.setName("李雷");Thread
hanMeiMei=newThread(box);
hanMeiMei.setName(“韩梅梅”);liLei.start();10.3创建线程的方法return;
10.4线程同步
使用相同目标对象的线程会共享目标对象的成员变量,有时这种情况需要避免,即当一个线
程访问共享成员变量时,即使该线程因休眠而中断,其它线程也需要等待,直到访问结束,其它
线程才可以进行访问,这种情况被称为线程同
步
或线程级安全。要实现线程同步,需要使用synchronized关键字修饰共享成员变量的访问方法,这个方法被称为同步方法。
10.4线程同步
同步方法中,sleep()方法的调用不会引起中断
。此
时
,若想通过程序设计中断同步,只能通
过Thread类中的wait()方法完成,而解除wait()
方法的中断需调用notifyAl1()方法。notifyAl1()方法会使所有因wait()方法调用而中
断的线程结束中断,按“先中断先入队”的原则进入等待队列,等待资源的空闲,准备从中断位
置继续执行。
10.4线程同步
例10-5classAccount{doublebalance;publicsynchronizedvoiddeposit(doublemoney){balance=balance+money;Sysntln("存入"+money+"
元,账户余额"+balance+"元。");Thread.sleep(1000);}catch(InterruptedExceptione){Sysntln(e);notifyAll();try{
10.4线程同步
publicsynchronizedvoidwithdraw(doublemoney){}catch(InterruptedExceptione){Sysntln(e);balance=balance-money;Sysntln("取出"+money+"元,账户余额"+balance+"元。while(balance<money){Sysntln("账户余额不足,等待存款。");try{
wait();
10.4线程同步
classSynchroTest
implements
Runnable{Thread
liLei,hanMeiMei;Accountaccount;SynchroTest(){liLei=new
Thread(this);hanMeiMei=newThread(this);account=new
Account();publicvoid
run(){if(Thread.currentThread()==liLei){for(int
i=1;i<=3;i++){Sysntln("李雷挣钱,将工资悉数存入家庭银行
…
…
.");account.deposit(1000);try{
10.4线程同步
Thread.sleep(2000);}catch(InterruptedExceptione){Sysntln(e);
(
(i
r;
3.c;
tThread()==hanMeiMei){Sysntln("韩梅梅把握家中的开支,从家庭银行取钱……");account.withdraw(800);publiccl
ss
Example10_5{publicstaticvoidmain(String[]args){SynchroTestsynchro=newSynchroTest();syncrt();syncrt();}aJ1hinte
iforels
10.5线程联合
当一个线程正在运行时,可以与另一个线程进
行联合,此时
,正在运行的线程会中断执行,将计
算机资源交给联合的线程,直到联合的线程运行结
束,才会结束中断,进入等待队列排队,准备获取计算机资源,恢复运行。线程对象调用join()方法,表示进行线程联合操作。由于join()方法声明
了InterruptedException
异常,因此在方法调用位
置需要进行异常捕获。例子10-6演示了线程联合。
10.5线程联合
例10-6classThreadJoinTest
implements
Runnable{Threadtourist,policeOffice;ThreadJoinTest(){tourist=newThread(this);tourist.setName(”李雷");publicvoid
run(){if(Thread.currentThread()==tourist){Sysntln("李雷计划去国外旅游,需要先到警察局办理护Thread.sleep(1000);policeOffice=newThread(this);policeOffice.start();policeOffice.join();try{
10.5线程联合
}catch(InterruptedExceptione){Sysntln(e);Sysntln("李雷拿到了护照,可以去办理签证,准备出国了。");
}elseif(Thread.currentThread()==policeOffice){try{Sysntln("李雷来到警察局正在填写申请表…….");Thread.sleep(1000);Sysntln("照相…….");Thread.sleep(1000);Sysntln("将申请表和照片交给警察审核…….");
10.5线程联合
Thread.sleep(1000);Sysntln("审核通过,交款,15个工作日后领取护照!");Thread.sleep(2000);}catch(InterruptedExceptione){■
Sysntln(e);■publicclass
Example10_6{■publicstatic
void
main(String[]args)ThreadJoinTest
joinTest=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 三年(2023-2025)黑龙江中考语文真题分类汇编:专题08 名著阅读(原卷版)
- 生产计划员岗位职责(3篇)
- 车险入门知识培训课件
- 车间防护安全工作培训课件
- 车间职工安全培训课件
- 酒店客房维修与保养制度
- 酒店市场营销策略制度
- (2025)前端开发岗位页面性能提升与跨端适配工作心得(2篇)
- 预付账款控制制度
- 《积的近似值》数学课件教案
- 江苏省2025年普通高中学业水平合格性考试英语试卷(含答案)
- 教学第九章-人体寄生虫概述课件
- 2020年华为采购物料环保规范?V4
- 绿化养护、保洁服务重点难点分析及解决措施
- 企业管理GoldenSample管理办法
- 湖北大学教职工登记表
- 2020年注册会计师(CPA)16第十六章收入、费用和利润(2020新教材版)课件
- 汇川伺服追剪控制指导说明完整版
- GB∕T 5273-2016 高压电器端子尺寸标准化(高清版)
- GB 190-2009 危险货物包装标志(高清版)
- 寒假学生托管报名登记表
评论
0/150
提交评论