本章学习目标2线程控制2.1线程状态2.2线程优先级1线程基础1.1线程的概念模型1.2创建线程两种方式1.3后台线程1.4GUI线程2.3线程串行化2.4线程休眠2.5线程让步2.6线程挂起和恢复3线程的同步3.1临界资源问题3.2互斥锁3.3死锁3.4线程同步通讯3.5生产者-消费者问题4多线程编程专题4.1线程间数据传输4.2类同步性与线程安全4.3定时器3JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校什么是线程线程是一个程序内部的顺序控制流。线程和进程¾每个进程都有独立的代码和数据空间(进程上下文),进程切换的开销大。¾线程:轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。¾多进程:在操作系统中能同时运行多个任务(程序)¾多线程:在同一应用程序中有多个顺序流同时执行4JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校,由java.lang.Thread类封装和虚拟;2.CPU所执行的代码,传递给Thread类对象;3.CPU所处理的数据,传递给Thread类对象。图16-1线程概念模型虚拟CPU代码数据5JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校创建线程Java的线程是通过java.lang.Thread类来实现的。每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。publicclassTestThread1{publicstaticvoidmain(Stringargs[]){Runner1r=newRunner1();Threadt=newThread(r);t.start();}}classRunner1implementsRunnable{publicvoidrun(){for(inti=0;i30;i++){System.out.println(No.+i);}}}例16-16JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校多线程Java中引入线程机制的目的在于实现多线程(Multi-Thread)publicclassTestThread2{publicstaticvoidmain(Stringargs[]){Runner2r=newRunner2();Threadt1=newThread(r);Threadt2=newThread(r);t1.start();t2.start();}}classRunner2implementsRunnable{publicvoidrun(){for(inti=0;i20;i++){Strings=Thread.currentThread().getName();System.out.println(s+:+i);}}}例16-27JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校多线程共享代码和数据多线程之间可以共享代码和数据。Runner2r=newRunner2();Threadt1=newThread(r);Threadt2=newThread(r);线程虚拟CPU代码数据t1Thread类对象t1Runner2类中的run方法Runner类型对象rt2Thread类对象t2Runner2类中的run方法Runner类型对象rclassMyRunnerimplementsRunnable{…}classYourRunnerimplementsRunnable{…}MyRunnerm=newMyRunner();YourRunnery1=newYourRunner();YourRunnery2=newYourRunner();Threadt1=newThread(m);Threadt2=newThread(y1);Threadt3=newThread(y2);Threadt4=newThread(y2);8JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校创建线程第二种方式直接继承Thread类创建线程publicclassTestThread3{publicstaticvoidmain(Stringargs[]){Threadt=newRunner3();t.start();}}classRunner3extendsThread{publicvoidrun(){for(inti=0;i30;i++){System.out.println(No.+i);}}}例16-39JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校接口创建线程:¾可以将CPU、代码和数据分开,形成清晰的模型;¾线程体run()方法所在的类还可以从其他类继承一些有用的属性或方法;¾并有利于保持程序风格的一致性。二.直接继承Thread类创建线程:¾Thread子类无法再从其他类继承¾编写简单,run()方法的当前对象就是线程对象,可直接操纵。10JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校后台线程相关基本概念:¾后台处理(BackgroundProcessing)¾后台线程(BackgroundThread/DaemonThread)¾用户线程(UserThread)¾主线程(MainThread)¾子线程(SubThread)Thread类提供的相关方法:¾publicfinalbooleanisDaemon()¾publicfinalvoidsetDaemon(Booleanon)举例:¾例16-4使用后台线程11JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程GUI程序运行过程中系统会自动创建若干GUI线程常见GUI线程:¾AWT-Windows线程¾AWT-EventQueue-n线程¾AWT-Shutdown线程GUI线程展示¾例16-5TestGUIThread.java12JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校运行状态线程生命周期线程的生命周期¾新建状态¾就绪状态¾运行状态¾阻塞状态¾终止状态阻塞状态就绪状态调度导致阻塞的事件阻塞解除终止状态新建状态线程基本状态转换start()run()执行完毕13JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程优先级线程的优先级用数字来表示,范围从1到10。主线程的缺省优先级是5,子线程的优先级默认与其父线程相同。Thread类提供的相关方法:¾publicfinalintgetPriority();¾publicfinalvoidsetPriority(intnewPriority)相关静态整型常量:¾Thread.MIN_PRIORITY=1¾Thread.MAX_PRIORITY=10¾Thread.NORM_PRIORITY=5用法举例:¾例16-6TestPriority.java14JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程串行化在多线程程序中,如果在一个线程运行的过程中要用到另一个线程的运行结果,则可进行线程的串型化处理。Thread类提供的相关方法:¾publicfinalvoidjoin()¾publicfinalvoidjoin(longmillis)¾publicfinalvoidjoin(longmillis,intnanos)用法举例:¾例16-7实现线程的串行化15JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程休眠线程休眠——暂停执行当前运行中的线程,使之进入阻塞状态,待经过指定的“延迟时间”后再醒来并转入到就绪状态。Thread类提供的相关方法:¾publicstaticvoidsleep(longmillis)¾publicstaticvoidsleep(longmillis,intnanos)用法举例:¾例16-8数字时钟16JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程让步线程让步——让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程阻塞,而是使之转入就绪状态。Thread类提供的相关方法:¾publicstaticvoidyield()用法举例:¾例16-9线程让步运行效果演示17JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校线程挂起和恢复线程挂起——暂时停止当前运行中的线程,使之转入阻塞状态,并且不会自动恢复运行。线程恢复——使得一个已挂起的线程恢复运行。Thread类提供的相关方法:¾publicfinalvoidsuspend()¾publicfinalvoidresume()用法举例:¾例16-10利用线程挂起/恢复机制实现倒记时器18JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校终止线程举例(1)publicclassTest{publicstaticvoidmain(Stringargs[]){Runnerr=newRunner();Threadt=newThread(r);t.start();for(inti=0;i10;i++){try{Thread.sleep(5);System.out.println(\ninthreadmaini=+i);}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println(Threadmainisover);r.shutDown();}}19JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校终止线程举例(2)publicclassRunnerimplementsRunnable{privatebooleanflag=true;publicvoidrun(){inti=0;while(flag==true){System.out.print(+i++);}}publicvoidshutDown(){flag=false;}}20JavaSEJavaSE应用程序设计应用程序设计新科海学校新科海学校()判断线程是否还“活”着,即线程是否还未终止。getPriority()获得线程的优先级数值setPriority()设置线程的优先级数值sleep()将当前线程睡眠指定毫秒数join()调用