【教学课件】第七讲多线程.ppt
《【教学课件】第七讲多线程.ppt》由会员分享,可在线阅读,更多相关《【教学课件】第七讲多线程.ppt(62页珍藏版)》请在三一办公上搜索。
1、第七讲 多线程,多线程基本概念 创建线程的方式 线程的生命周期及控制 线程的优先级及调度 多线程的互斥与同步 守护线程(Daemon)线程组(ThreadGroup),并发现象在现实生活中大量存在人体(消化、运动)计算机(同时运行多中程序)多线程在一个程序中实现并发编程语言一般提供了串行程序设计的方法计算机的并发能力由操作系统提供Java在语言级提供多线程并发的概念,1、多线程基本概念,1、多线程基本概念,以前所编写的程序,每个程序都有一个入口、一个出口以及一个顺序执行的序列,在程序执行过程中的任何指定时刻,都只有一个单独的执行点。事实上,在单个程序内部是可以在同一时刻进行多种运算的,这就是所
2、谓的多线程(这与多任务的概念有相似之处)。一个单独的线程和顺序程序相似,也有一个入口、一个出口以及一个顺序执行的序列,从概念上说,一个线程是一个程序内部的一个顺序控制流。线程并不是程序,它自己本身并不能运行,必须在程序中运行。在一个程序中可以实现多个线程,这些线程同时运行,完成不同的功能。,将军令,多线程,1、多线程基本概念,从逻辑的观点来看,多线程意味着一个程序的多行语句同时执行,但是多线程并不等于多次启动一个程序,操作系统也不会把每个线程当作独立的进程来对待:两者的粒度不同,是两个不同层次上的概念。进程是由操作系统来管理的,而线程则是在一个程序(进程)内。不同进程的代码、内部数据和状态都是
3、完全独立的,而一个程序内的多线程是共享同一块内存空间和同一组系统资源,有可能互相影响。线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小。,1、多线程基本概念,进程:程序的一次执行。程序代码程序数据程序资源线程:进程中程序代码的一个执行序列。程序调用堆栈线程局部变量可共享访问进程中的数据和资源操作系统按线程来调度程序的执行,1、多线程基本概念,1、多线程基本概念,1、多线程基本概念,多线程的优势:多线程编程简单,效率高(能直接共享数据和资源,多进程不能)适合于开发服务程序(如Web服务,聊天服务等)适合于开发有多种交互接口的程序(如聊天程序的客户
4、端,网络下载工具)适合于有人机交互又有计算量的程序(如字处理程序Word,Excel)减轻编写交互频繁、涉及面多的程序的困难(如监听网络端口)程序的吞吐量会得到改善(同时监听多种设备,如网络端口、串口、并口以及其他外设)有多个处理器的系统,可以并发运行不同的线程(否则,任何时刻只有一个线程在运行),1、多线程基本概念,虽然各种操作系统(Unix/Linux、Windows系列等)都支持多线程,但若要用C、C+或其他语言编写多线程程序是十分困难的,因为它们对数据同步的支持不充分。对多线程的综合支持是Java语言的一个重要特色,它提供了Thread类来实现多线程。在Java中,线程可以认为是由三部
5、分组成的:虚拟CPU,封装在类中,它控制着整个线程的运行;执行的代码,传递给Thread类,由Thread类控制顺序执行;处理的数据,传递给Thread类,是在代码执行过程中所要处理的数据。,2、创建线程的方式,Java的线程是通过Java的软件包java.lang中定义的类Thread来实现的。当生成一个Thread类的对象之后,就产生了一个线程,通过该对象实例,可以启动线程、终止线程、或者暂时挂起线程等。,2、创建线程的方式,Thread类本身只是线程的虚拟CPU;线程所执行的代码(或者说线程所要完成的功能)是通过方法run()(包含在一个特定的对象中)来完成的,方法run()称为线程体。
6、实现线程体的特定对象是在初始化线程时传递给线程的。在一个线程被建立并初始化以后,Java的运行时系统就自动调用run()方法,正是通过run()方法才使得建立线程的目的得以实现。通常,run()方法是一个循环,例如一个播放动画的线程要循环显示一系列图片。有时,run()方法会执行一个时间较长的操作,例如下载并播放一个JPEG格式的电影。,先来看看线程对象的初始化,类Thread的构造方法如下:public Thread(ThreadGroup group,Runnable target,String name)group指明了线程所属的线程组;target是线程体run()方法所在的对象;na
7、me是线程的名称。target必须实现接口Runnable。在接口Runnable中只定义了一个方法void run()作为线程体。任何实现接口Runnable的对象都可以作为一个线程的目标对象。类Thread本身也实现了接口Runnable(空实现),因此,上述构造方法中各参数都可以为null。,2、创建线程的方式,从Thread类的构造方法可以看出,用户可以有两种方法构造自己的run()方法。方法一:定义一个线程类,它继承类Thread并重写其中的方法run()。这时在初始化这个类的实例时,目标对象target可以为null,表示这个实例本身具有线程体。由于Java只支持单继承,用这种方法
8、定义的类不能再继承其他类。,2、创建线程的方式,class SimpleThread extends Thread public SimpleThread(String str)super(str);public void run()for(int i=0;i 10;i+)System.out.println(i+getName();try sleep(int)(Math.random()*1000);catch(InterruptedException e)System.out.println(DONE!+getName();,TwoThreadsTest.java,2、创建线程的方式,方法
9、二:提供一个实现接口Runnable的类作为线程的目标对象。在初始化一个Thread类或子类生成线程实例时,把目标对象传递给这个线程实例,由该目标对象提供线程体run()方法。这时,实现接口Runnable的类还可以再继承其他类,即实现接口Runnable的类可以不单纯是提供线程体。,2、创建线程的方式,public class Clock extends java.applet.Applet implements Runnable Thread clockThread;public void start()if(clockThread=null)clockThread=new Thread(
10、this,Clock);clockThread.start();public void run()while(clockThread!=null)repaint();try clockThread.sleep(1000);catch(InterruptedException e)public void paint(Graphics g)Date now=new Date();g.drawString(now.getHours()+:+now.getMinutes()+:+now.getSeconds(),5,10);public void stop()clockThread.stop();cl
11、ockThread=null;,Clock.java,run()方法是运行线程的主体,启动线程时,由java直接调用public void run()。使用Runnable接口可以将线程的虚拟CPU、代码和数据分开,形成一个比较清晰的模型。使用Runnable接口使得包含线程体的类还可以继承其他类。直接继承Thread类以后不能再继承其他类,但编写简单,并可直接操纵线程;使用Runnable接口时,若要在run()方法中操纵线程,必须使用Thread.currentThread()方法。在具体应用中,采用哪种方法来构造线程体要根据具体情况而定。通常,当一个线程体所在的类已经继承了另一个类时,就
12、应该用实现Runnable接口的方法。,2、创建线程的方式,2、创建线程的方式,Thread类的方法void run()线程所执行的代码void start()throws IllegalThreadStateException使程序开始执行,多次调用会产生例外void sleep(long milis)让线程睡眠一段时间,此期间线程不消耗CPU资源void interrupt()中断线程static boolean interrupted()判断当前线程是否被中断(会清除中断状态标记)boolean isInterrupted()判断指定线程是否被中断,线程状态控制方法,2、创建线程的方式,
13、Thread类的方法boolean isAlive()判断线程是否处于活动状态(即已调用start,但run还未返回)static Thread currentThread()返回当前线程对象的引用void setName(String threadName)改变线程的名字String getName()获得线程的名字String toString()例子:ThreadThread-0,1,testvoid join(longmillis,intnanos)等待线程结束,2、创建线程的方式,Thread类的方法void destroy()销毁线程void stop()终止线程的执行void s
14、uspend()/void resume()挂起线程/static void yield()暂停当前线程,让其他线程执行void setDaemon(boolean on)/void setPriority(int p)获得线程的名字notify()/notifyAll()/wait()从Object继承而来,3、线程的生命周期及控制,线程是程序内部的一个顺序控制流,它具有一个特定的生命周期。在一个线程的生命周期中,它总处于某一种状态中。线程的状态表示了线程正在进行的活动以及在这段时间内线程能完成的任务。,3、线程的生命周期及控制,born,ready,running,waiting,slee
15、ping,dead,blocked,start(),dispatch,quantum expirationyield(),wait,sleep(),run complete,issue I/O request,wait interval expiresnotify()notifyAll()interrupt(),I/O complete,sleep interval expiresinterrupt(),3、线程的生命周期及控制,3、线程的生命周期及控制,创建状态(new Thread)当创建了一个新的线程时(myThread thd=new myThread();),它就处于创建状态,此时它
16、仅仅是一个空的线程对象,系统不为它分配资源。处于这种状态时只能启动或终止该线程,调用除这两种以外的其它线程状态相关的方法都会失败并且会引起非法状态例外IllegalThreadStateException(对于其它状态,若所调用的方法与状态不符,都会引起非法状态例外)。,可运行状态(Runnable)当线程处于创建状态时,可以调用start()方法(thd.start();)来启动它,产生运行这个线程所需的系统资源,安排其运行,并调用线程体run()方法,这样就使得该线程处于可运行(Runnable)状态。需要注意的是这一状态并不是运行中状态(Running),因为线程也许实际上并未真正运行(
17、Ready)。由于很多计算机都是单处理器的,所以要在同一时刻运行所有的处于可运行状态的线程是不可能的,Java运行系统必须实现调度来保证这些线程共享处理器。但是在大多数情况下,可运行状态也就是运行中。当一个线程正在运行时,它是可运行的,并且也是当前正运行的线程。,3、线程的生命周期及控制,3、线程的生命周期及控制,不可运行状态(Not Runnable)线程处于可运行状态时,当下面四种情况发生,线程就进入不可运行状态:调用了sleep()方法;调用了suspend()方法;为等候一个条件变量,线程调用wait()方法;输入输出流中发生线程阻塞。,Thread myThread=new MyTh
18、readClass();myThread.start();try myThread.sleep(10000);catch(InterruptedException e),不可运行状态(Not Runnable)对于这四种使得线程处于不可运行状态的情况,都有特定的方法使线程返回可运行状态:如果线程处于睡眠状态中,sleep()方法中的参数为休息时间,当这个时间过去后,线程即为可运行的;如果一个线程被挂起,须调用resume()方法来返回;如果线程在等待条件变量,那么要停止等待的话,需要该条件变量所在的对象调用notify()或notifyAll()方法;如果在I/O流中发生线程阻塞,则特定的I/
19、O指令将结束这种不可运行状态。需要注意的是每种方法都仅仅对相应的情况才有作用,例如当一个线程睡眠并且睡眠时间还没有结束时,调用resume()方法是无效的,并且还会引起非法状态例外。,3、线程的生命周期及控制,死亡状态(Dead)线程的终止一般可通过两种方法实现:自然撤消或是被停止。自然撤消是指从线程的run()方法正常退出;而调用线程的实例方法stop()则可以强制停止当前线程。,3、线程的生命周期及控制,/线程自然撤销public void run()int i=0;while(i 100)i+;System.out.println(i=+i);,/线程被强行停止myThread thd=
20、new MyThread();thd.start();try thd.sleep(10000);catch(InterruptedException e)thd.stop();,3、线程的生命周期及控制,可以通过在其他线程中调用stop()方法来终止线程,也可以由线程自己调用stop()方法,自我终止。如果希望线程正常终止,可采用标记来使线程中的run()方法退出。,/线程自我终止public void run()while(true)/完成线程的特定功能 if(time_to_die)Thread.currentThread().stop();,public class Xyz implem
21、ents Runnable private boolean timeToQuit=false;public void run()while(!timeToQuit)public void stopRunning()timeToQuit=true;,3、线程的生命周期及控制,public class ControlThread private Xyz r=new Xyz();private Thread t=new Thread(r);public void startThread()t.start();publi void stopThread()r.stopRunning();,3、线程的生
22、命周期及控制,isAlive()方法:可以用来判断线程目前是否正在执行中。如果线程已被启动并且未被终止,那么isAlive()返回true,但该线程是可运行或是不可运行的,是不能作进一步的分辨。如果返回false,则该线程是新创建或是已被终止的(同样不能作进一步的分辨)。join()方法:等待线程执行完毕。yield()方法:将执行的权力交给其它优先级相同的线程,当前执行线程到可运行线程队列(ready)的最后等待,若队列空,该方法无效。,myThread thd=new MyThread();thd.start();thd.join();/等待线程thd执行完后再继续往下执行,join(in
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 教学课件 教学 课件 第七 多线程
链接地址:https://www.31ppt.com/p-5660549.html