




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Java 多线程 多线程的概念;多线程的概念; 线程的生命周期;线程的生命周期; 多线程编程中的常量和方法;多线程编程中的常量和方法; 线程调度方法;线程调度方法; 资源冲突与协调;资源冲突与协调; 线程之间的通信。线程之间的通信。 Java中多线程的基本概念 在多线程模型中,多个线程共存于同一块内存中,在多线程模型中,多个线程共存于同一块内存中, 且共享资源。且共享资源。 每个线程分配有限的时间片来处理任务。由于每个线程分配有限的时间片来处理任务。由于 CPUCPU在各个线程之间的切换速度非常快,用户在各个线程之间的切换速度非常快,用户 感觉不到,从而认为并行运行。感觉不到,从而认为并行运行
2、。 多线程的特点 多个线程在运行时,系统自动在线程之间进行切多个线程在运行时,系统自动在线程之间进行切 换;换; 由于多个线程共存于同一块内存,线程之间的通由于多个线程共存于同一块内存,线程之间的通 信非常容易;信非常容易; JavaJava将线程视为一个对象。线程要么是将线程视为一个对象。线程要么是ThreadThread类类 的对象,要么是接口的对象,要么是接口RunnableRunnable的对象。的对象。 多线程的特点(续) 当多个线程并行执行时,具有较高优先级的线当多个线程并行执行时,具有较高优先级的线 程将获得较多的程将获得较多的CPUCPU时间片;时间片; 优先级是从优先级是从0
3、 0到到1010的整数,并且它仅表示线程之的整数,并且它仅表示线程之 间的相对关系;间的相对关系; 多个线程共享一组资源,有可能在运行时产生多个线程共享一组资源,有可能在运行时产生 冲突。必须采用冲突。必须采用synchronizedsynchronized关键字协调资关键字协调资 源,实现线程同步。源,实现线程同步。 多线程编程中常用的常量和方法 线程类线程类ThreadThread定义在定义在java.langjava.lang包中;包中; ThreadThread类包含的常量有:类包含的常量有: 1. public static final int MAX_PRIORITY: 最大优先
4、级,值是10。 2. public static final int MIN_PRIORITY: 最小优先 级,值是1。 3. public static final int NORM_PRIORITY:缺省优 先级,值是5。 多线程编程中常用的常量和方法(续) 常用方法:常用方法: currentThread( ):返回当前运行的线程对象,是一个静态 的方法。 sleep(int n):使当前运行的线程睡n个毫秒,然后继续执 行,也是静态方法。 yield( ):使当前运行的线程放弃执行,切换到其它线程, 是一个静态方法。 isAlive( ):判断线程是否处于执行的状态,返回值true表
5、示处于运行状态,false表示已停止。 多线程编程中常用的常量和方法(续) start( ):使调用该方法的线程开始执行。 run( ):该方法由start( )方法自动调用。 stop( ):使线程停止执行,并退出可执行状态。 suspend():使线程暂停执行,不退出可执行态。 resume( ):将暂停的线程继续执行。 setName(String s):赋予线程一个名字。 getName( ):获得调用线程的名字。 多线程编程中常用的常量和方法(续) getPriority( ):获得调用线程的优先级。 setPriority(int p):设置线程的优先级。 join( ):等待线程
6、死亡,若中断了该线程,将抛出异常。 多线程编程中常用的常量和方法(续) 注意注意1 1:在创建线程对象时,缺省的线程优先级:在创建线程对象时,缺省的线程优先级 是是5 5,一般设置优先级,一般设置优先级4 4到到6 6之间,不要设置为之间,不要设置为 1010,否则其它线程将执行不到。,否则其它线程将执行不到。 注意注意2 2:JavaJava的调度器能使高优先级的线程始终的调度器能使高优先级的线程始终 运行,一旦运行,一旦CPUCPU有空闲,具有同等优先级的线有空闲,具有同等优先级的线 程,以轮流的方式顺序使用时间片。程,以轮流的方式顺序使用时间片。 线程的生命周期 resume suspe
7、nd wait stop I/O 请求结束 start notify notifyAll I/O 请求 睡眠时间结束 sleep 分配时间片 时间片结束 创建 就绪 运行 结束 挂起 阻塞 睡眠 等待 class getThreadInfo / 单线程示例单线程示例 public static void main(String args ) String name; int p; Thread curr; curr=Thread.currentThread( ); System.out.println(当前线程当前线程: +curr); name=curr.getName( ); p=curr
8、.getPriority( ); System.out.println(线程名线程名: +name); System.out.println(优先级优先级 :+p); 程序输出结果: 当前线程: Threadmain,5,main 线程名 : main 优先级 :5 创建多线程的方法 方法方法1 1:通过通过ThreadThread类的子类实现多线程。类的子类实现多线程。 方法方法2 2:定义一个实现定义一个实现RunnableRunnable接口的类实现多接口的类实现多 线程。线程。 创建多线程的方法(续) 方法方法1 1:通过创建通过创建ThreadThread类的子类实现多线程,类的子类
9、实现多线程, 步骤如下步骤如下 :1. 定义Thread类的一个子类。 2. 定义子类中的方法run( ),覆盖父类中的 方法run( )。 3. 创建该子类的一个线程对象。 4. 通过start( )方法启动线程。例如程序2: / 程序程序2 class UserThread extends Thread int sleepTime; public UserThread(String id) / 构造函数构造函数 super(id); sleepTime=(int)(Math.random( )*1000); System.out.println(线程名:线程名: +getName( )+
10、,睡眠:睡眠: +sleepTime+ 毫秒 毫秒); public void run( ) try / 通过线程睡眠模拟程序的执行通过线程睡眠模拟程序的执行 Thread.sleep(sleepTime); catch(InterruptedException e) System.err.println(运行异常运行异常: + e.toString( ); System.out.println(运行的线程是:运行的线程是:+ getName( ); public class multThreadTest public static void main(String args ) UserTh
11、readt1,t2,t3,t4; t1=new UserThread(NO 1); t2=new UserThread(NO 2); t3=new UserThread(NO 3); t4=new UserThread(NO 4); t1.start( );t2.start( ); t3.start( );t4.start( ); 程序某次的运行结果: 线程名: NO 1,睡眠: 885 毫秒 线程名: NO 2,睡眠: 66 毫秒 线程名: NO 3,睡眠: 203 毫秒 线程名: NO 4,睡眠: 294 毫秒 目前运行的线程是:NO 2 目前运行的线程是:NO 3 目前运行的线程是:NO
12、 4 目前运行的线程是:NO 1 注意:注意:Thread类中的类中的run( )方法具有方法具有public属属 性,覆盖该方法时,前面必须带上性,覆盖该方法时,前面必须带上public。 创建多线程的方法(续) 方法方法2 2:通过接口创建多线程,步骤如下:通过接口创建多线程,步骤如下: 1.定义一个实现Runnable接口的类。 2.定义方法run( )。Runnable接口中有一个空的 方法run( ),实现它的类必须覆盖此方法。 3.创建该类的一个线程对象,并将该对象作参 数,传递给Thread类的构造函数,从而生成 Thread类的一个对象。 / 注意这一步! 4.通过start(
13、 )方法启动线程。例如: / 程序程序3 class UserMultThread implements Runnable int num; UserMultThread(int n) num=n; public void run( ) for(int i=0;i3;i+) System.out.println(运行线程:运行线程:+num); System.out.println(结束结束 : +num); public class multThreadZero public static void main(String args ) throws InterruptedException
14、 Thread mt1=new Thread( new UserMultThread(1); Thread mt2=new Thread( new UserMultThread(2); mt1.start( ); mt2.start( ); mt1.join( ); / 等待线程死亡等待线程死亡 mt2.join( ); 程序运行某次的输出结果: 运行线程:1 运行线程:2 运行线程:1 运行线程:2 运行线程:1 运行线程:2 结束 : 1 结束 : 2 创建多线程的方法(续) 程序程序3 3中需要注意的中需要注意的2 2点:点: 1.1. mt1.join( )mt1.join( )是等待
15、线程死亡,对该方法必是等待线程死亡,对该方法必 须捕捉异常,或通过须捕捉异常,或通过throwsthrows关键字指明可能关键字指明可能 要发生的异常。要发生的异常。 2.2. 对一个线程不能调用对一个线程不能调用start( )start( )两次,否则会两次,否则会 产生产生IllegalThreadStateExceptionIllegalThreadStateException异常异常。 线程调度模型 线程调度程序挑选线程时,将选择处于就绪状态线程调度程序挑选线程时,将选择处于就绪状态 且优先级最高的线程。且优先级最高的线程。 如果多个线程具有相同的优先级,它们将被轮流如果多个线程具有
16、相同的优先级,它们将被轮流 调度。调度。 程序程序4 4验证了验证了JavaJava对多线程的调度方法。对多线程的调度方法。 class threadTest extends Thread / 程序程序4 threadTest(String str) super(str); public void run( ) try Thread.sleep(2); catch(InterruptedException e) System.err.println(e.toString( ); System.out.println(getName( )+ + getPriority( ); public cl
17、ass multTheadOne public static void main(String agrs) Thread one=new threadTest(one ); Thread two=new threadTest(two ); Thread three=new threadTest(three ); one.setPriority(Thread.MIN_PRIORITY); two.setPriority(Thread.NORM_PRIORITY); three.setPriority(Thread.MAX_PRIORITY); one.start( ); two.start( )
18、; three.start( ); 程序输出结果: three 10 two 5 one 1 思考:在run()方法中,通过线程睡眠2个毫秒, 模拟程序的执行。如果不睡眠,你知道输出 什么结果吗?为什么? 资源冲突 多个线程同时运行虽然可以提高程序的执行效多个线程同时运行虽然可以提高程序的执行效 率,但由于共享一组资源,可能会产生冲突,率,但由于共享一组资源,可能会产生冲突, 例如程序例如程序5 5 。 class UserThread / 程序程序5 void Play(int n) System.out.println(运行线程运行线程 NO:+n); try Thread.sleep(3
19、); catch(InterruptedException e) System.out.println(“线程异常线程异常, NO:+n); System.out.println(结束线程结束线程 NO:+n); class UserMultThread implements Runnable UserThread UserObj; int num; UserMultThread(UserThread o,int n) UserObj=o; num=n; public void run( ) UserObj.Play(num); public class multTheadTwo public
20、 static void main(String args ) UserThread Obj=new UserThread( ); Thread t1=new Thread( new UserMultThread(Obj,1); Thread t2=new Thread( new UserMultThread(Obj,2); Thread t3=new Thread( new UserMultThread(Obj,3); t1.start( );t2.start( );t3.start( ); 程序输出结果: 运行线程 NO:1 运行线程 NO:3 结束线程 NO:1 结束线程 NO:3 运行
21、线程 NO:2 结束线程 NO:2 同步方法 JavaJava通过关键字通过关键字synchronizedsynchronized实现同步。实现同步。 当对一个对象当对一个对象( (含方法含方法) )使用使用synchronizedsynchronized,这个,这个 对象便被锁定或者说进入了监视器对象便被锁定或者说进入了监视器。在一个时在一个时 刻只能有一个线程可以访问被锁定的对象。它刻只能有一个线程可以访问被锁定的对象。它 访问结束时,让高优先级并处于就绪状态的线访问结束时,让高优先级并处于就绪状态的线 程,继续访问被锁定的对象程,继续访问被锁定的对象,从而实现资源同从而实现资源同 步。步
22、。 加锁的方法有加锁的方法有两种两种:锁定冲突的对象,或锁定冲:锁定冲突的对象,或锁定冲 突的方法。突的方法。 同步方法(续) 1.1. 锁定冲突的对象锁定冲突的对象。语法格式:。语法格式: synchronized ( ObjRef ) Block / 需要同步执行的语句体需要同步执行的语句体 锁定对象可以出现在锁定对象可以出现在任何任何一个方法中。例如,一个方法中。例如, 修改程序修改程序9-5中的方法中的方法run( ) 如下:如下: public void run( ) synchronized(UserObj) UserObj.Play(num); 运行结果如下: 运行线程 NO:1
23、 结束线程 NO:1 运行线程 NO:2 结束线程 NO:2 运行线程 NO:3 结束线程 NO:3 同步方法(续) 2.2. 锁定冲突的方法锁定冲突的方法。语法格式:。语法格式: synchronized 方法的定义 例如,修改程序5中的方法Play( ) 如下: synchronized void Play(int n) / 中间的程序代码略 注意: 1. 对方法run( )无法加锁,不可避免冲突; 2. 对构造函数不能加锁,否则出现语法错误。 线程间通信 多线程通信的方法有两种:多线程通信的方法有两种: 1.1. 把共享变量和方法封装在一个类中实现;把共享变量和方法封装在一个类中实现;
24、2.2. 通过通过wait( )wait( )和和notify( )notify( )方法实现。方法实现。 通过封装共享变量实现线程通 信 程序6演示了通过将共享变量封装在一个 类中,实现线程通信 class comm /共享类共享类 private int n; private boolean bool=false; void produce(int i) while(bool) n=i; bool=true; System.out.println(n 产生数据:产生数据:+n); void readout( ) while(!bool) bool=false; System.out.pri
25、ntln( 读取数据:读取数据:+n); / 读取数据类读取数据类 class dataProducer implements Runnable comm cm; dataProducer(comm c) cm=c; public void run( ) / 生产者产生生产者产生5个随机数个随机数 for(int i=0;i5;i+) duce(int)(Math.random( )*100); class dataConsumer implements Runnable comm cm; dataConsumer(comm c) cm=c; public void run( )
26、for(int i=0;i5;i+) cm.readout( ); / 消费者读取数据消费者读取数据 public class multTheadThree public static void main(String args ) comm cm=new comm( ); Thread t1=new Thread( /无名对象做参数无名对象做参数 new dataProducer(cm); Thread t2=new Thread( new dataConsumer(cm); t1.start( ); t2.start( ); 程序的某次运行结果: 产生数据:81 读取数据:81 产生数据:
27、15 读取数据:15 产生数据:92 读取数据:92 产生数据:98 读取数据:98 产生数据:79 读取数据:79 通过系统方法实现线程通信 线程同步控制的第二种方法是采用如下几个系统线程同步控制的第二种方法是采用如下几个系统 方法:方法: 1.1.wait( )wait( )方法:使一个线程进入等待状态,直到方法:使一个线程进入等待状态,直到 被唤醒。被唤醒。 2.2.notify( )notify( )方法:通知等待监视器的线程,该对方法:通知等待监视器的线程,该对 象的状态已经发生了改变。象的状态已经发生了改变。 3.3. notifyAll( )notifyAll( )方法:唤醒从同
28、一个监视器中用方法:唤醒从同一个监视器中用 wait( )wait( )方法退出的所有线程,使它们按照优先方法退出的所有线程,使它们按照优先 级的顺序重新排队。例如级的顺序重新排队。例如程序程序7 7。 class comm / 程序程序7 private int n; private boolean bool=false; synchronized void produce(int i) if(bool) try wait( ); catch(InterruptedException e) System.out.println(comm 出现异常出现异常); else n=i; bool=t
29、rue; System.out.println(n产生数据:产生数据: +n); notify( ); / 唤醒另外一个线程唤醒另外一个线程 synchronized void readout( ) if(!bool) try wait( ); catch(InterruptedException e) System.out.println( comm 出现异常出现异常); else bool=false; System.out.println(读取数据:读取数据: +n); notify( ); / 唤醒另一个线程唤醒另一个线程 class dataProducer implements Runnable comm cm; dataProducer (comm c) cm=c; public void run( ) try for(int i=0;i5;i+) duce(int)(Math.random( )
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 餐饮业顾客满意度调查表
- 家长会发言稿
- 《电阻电路分析基础:高中物理电学教案》
- 机械设计制造及其自动化测试卷
- 数控技术作业指导书
- 工程技术咨询服务合同样式
- 老照片修复效果统计表
- 专项施工方案应具有
- 劳务安全生产协议书
- 上海中心 施工方案
- 莫塔全科医学安全诊断策略
- 保密法实施条例解读培训
- (正式版)SHT 3225-2024 石油化工安全仪表系统安全完整性等级设计规范
- 第一单元《欢天喜地》第一课 《多彩的节日》(教案)三年级下册《人文与社会》黑龙江地方课程
- (高清版)DZT 0291-2015 饰面石材矿产地质勘查规范
- 2024全国职业院校技能大赛ZZ059安全保卫赛项规程+赛题
- 超高分子量聚乙烯纤维发展前景分析
- 脑梗死伴发高血压的护理
- 派出所开展小学安全教育讲座
- 2024年全国公务员考试公共基础知识C类真题及解析
- 社交电商“小红书”发展现状分析
评论
0/150
提交评论