《第十章多线程精选文档.ppt》由会员分享,可在线阅读,更多相关《第十章多线程精选文档.ppt(58页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第十章多线程本讲稿第一页,共五十八页1本讲内容10.1线程的概念10.2Java中多线程的编程10.3线程的同步与死锁本讲稿第二页,共五十八页10.1线程的概念1.程序、进程和线程程序、进程和线程1程序是为完成特定任务、用某种语言编写的一组指令的集合。指一段静态的代码。2进程是程序的一次执行过程,是系统进行调度和资源分配的一个独立单位。3进程中的一小段程序代码称为线程。本讲稿第三页,共五十八页2线程的主要特点线程的主要特点:1不能以一个文件名的方式独立存在在磁盘中;不能单独执行,只有在进程启动后才可启动;各线程间共享进程空间的数据(代码与数据).2线程是比进程更小一级的执行单元。3一个进程在其
2、执行过程中,可以产生多个线程,形成多条执行线索。4每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。5一个线程有它自己的入口和出口,以及一个顺序执行的序列6线程不能独立存在,必须存在于进程中,线程线程创建、销毁和切换的负荷远小于进程,又称为轻量级进程(lightweightprocess)。系统负担小,主要是CPU的分配。本讲稿第四页,共五十八页3.进程进程是正在运行的一个程序n程序:静态对象进程:动态过程n操作系统为每个进程分配一段内存空间,包括:代码、数据以及堆栈等资源n多任务的操作系统(OS)中,进程切换对CPU资源消耗较大本讲稿第五页,共五十八页4.多线程1多线程是指同时
3、存在几个执行体,按几条不同的执行线索共同工作的情况。2多线程实现单个进程中的并发计算。3各线程间共享进程空间的数据,并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。4多线程的程序能更好地表述和解决现实世界的具体问题,是计算机应用开发和程序设计的一个必然发展趋势。本讲稿第六页,共五十八页本讲稿第七页,共五十八页进程与多线程单线程多线程进程传统进程多线程进程本讲稿第八页,共五十八页5.线程的调度调度策略时间片抢占式:高优先级的线程抢占CPUnJava的调度方法同优先级线程组成先进先出队列,使用时间片策略对高优先级,使用优先调度的抢占式策略12本讲稿第九页,共五十八页6.Java与多线程
4、1Java语语言言的的一一个个重重要要功功能能特特点点:就是内置对多线程的支持,它使得编程人员可以很方便地开发出具有多线程功能,能同时处理多个任务的功能强大的应用程序。2每个每个Java程序都有一个隐含的主线程程序都有一个隐含的主线程每个Java程序都有一个主线程,对于APPLICATION程序,主线程是main()函数执行的线索;对于Applet程序指挥浏览器加载并执行Java小程序,要想实现多线程,必须在主线程中创建新的线程对象。3线程的用途:线程的用途:利用它可以完成重复性的工作(如实现动画、声音等的播放);从事一次性较费时的初始化工作(如网络连接、声音数据文件的加载,但对图像文件*.g
5、if、*.jpeg在java中自动地在后台载入、因而可不必设计图像载入的线程);并行的执行效果(一个进程多个线程)。本讲稿第十页,共五十八页6.线程的生命周期n要想实现线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态:1新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态2就绪:处于新建状态的线程被启动后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件3运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能4阻塞:在某
6、种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态5死亡:线程完成了它的全部工作或线程被提前强制性地中止stop()或destroy()线程死亡不具有继续运行能力线程死亡有两个原因:_正常执行的线程完成它的全部工作,即执行完run()方法的最后一句并退出_线程被强制终止,如stop()方法、destroy()方法本讲稿第十一页,共五十八页线程的生命周期本讲稿第十二页,共五十八页线程的生命周期(续)nNewborn:线程已创建,但尚未执行nRunnable:(就绪)线程已被调度,按优先级和先到先服务原则在队列中排队等待CPU时间片资源nRunnnig:正在
7、运行nBlocked:(阻塞)因某事件或睡眠而被暂时性地挂起nDead:正常/强行中断,退出运行状态本讲稿第十三页,共五十八页线程状态新建状态new Thread(.)就绪状态start()等待状态执行状态I/Osleep()CPU调度run()结束stop()yield()消亡 I/O完成sleep时间到本讲稿第十四页,共五十八页Java对多线程的支持提供对多线程的支持nThread类start(),stop(),run()nRunnable接口n实现多线程的两种编程方法继承Thread类实现Runnable接口本讲稿第十五页,共五十八页Thread类nThread类综合了Java程序中一个
8、线程需要拥有的属性和方法n当生成一个Thread类的对象后,一个新的线程诞生了。n每个线程都是通过目标对象的方法run()来完成其操作的。方法run()称为线程体(线程方法)。n提供线程体的目标对象是在初始化一个线程时指明的。n任何实现了Runnable接口(实现run()方法)的类实例都可以作为线程的目标对象。本讲稿第十六页,共五十八页方法之一:继承Thread类nThread类的重要方法:run()定义线程的具体操作系统调度此线程时自动执行初始时无具体操作内容n如何编程呢?继承Thread类,定义 run()方法本讲稿第十七页,共五十八页Thread类njava.lang包n构造函数Thr
9、ead();Thread(Stringthreadname);指定线程实例名n线程的优先级控制三个常量:MAX_PRIORITY10;MIN_PRIORITY1;NORM_PRIORITY5;getPriority()返回线程优先值setPriority(intnewPriority)改变线程的优先级线程创建时继承父线程的优先级本讲稿第十八页,共五十八页Thread类的有关方法nvoidstart():由Newborn到Runnable启动线程nStringgetName():返回线程的名称nrun():线程在被调度时执行的操作nstaticvoidsleep(指定时间毫秒):令当前活动线程在
10、指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队产生例外InterruptedException用try块调用sleep(),用catch块处理例外本讲稿第十九页,共五十八页Thread类的有关方法(续)nsuspend():挂起线程,处于阻塞状态nresume():恢复挂起的线程,重新进入就绪队列排队应用:可控制某线程的暂停与继续方法:设一状态变量suspendStatus=false(初始)暂停:if(!suspendStatus)T.suspend();suspendStatus=true;继续:if(suspendStatus)T.resume();suspendS
11、tatus=false;本讲稿第二十页,共五十八页Thread类的有关方法(续)nstaticvoidyield():对正在执行的线程若就绪队列中有与当前线程同优先级的排队线程,则当前线程让出CPU控制权,移到队尾若队列中没有同优先级的线程,忽略此方法nstop():强制线程生命期结束nbooleanisAlive():返回boolean,表明是否线程还存在nstaticcurrentThread():返回当前线程本讲稿第二十一页,共五十八页生成与运行线程方法1MyThread mt=new MyThread();mt.start();class MyThread extends Thread
12、 public void run()线程体 执行run()方法本讲稿第二十二页,共五十八页建立线程线程控制(虚拟CPU)线程代码被操作数据Thread类的子类的实例 (mt)Thread类的子类提供 的run方法Thread子类实例(mt)本讲稿第二十三页,共五十八页Thread类方法总结n启动线程:start()n有关线程执行的控制:stop()、suspend()、resume()n有关调度控制Thread.sleep(10);/低优先级的线程也可以获得执行Thread.yield();/同优先级的线程可以获得执行suspend();/暂停本线程本讲稿第二十四页,共五十八页方法之二:Run
13、nablenRunnable接口自定义类实现Runnable接口使用Thread类的另一构造函数:uThread(Runnable,String)用实现了Runnable接口的类的对象中所定义的run()方法,来覆盖新创建的线程对象的run()方法使用start()启动线程本讲稿第二十五页,共五十八页方法之二:Runnable(续)n例:classAimplementsRunnablepublicvoidrun().classBpublicstaticvoidmain(Stringarg)Runnablea=newA();Threadt=newThread(a);t.start();本讲稿第二
14、十六页,共五十八页建立线程例public class ThreadTest public static void main(String args)Job1 j=new Job1();Thread t1=new Thread(j);t1.start();class Job1 implements Runnable int i=1;public void run()while(i50)System.out.println(i+);本讲稿第二十七页,共五十八页建立线程线程控制(虚拟CPU)线程代码被操作数据Thread的实例(t1)由实现了Runnable接口的类(Job1)提供run方法实现Ru
15、nnable接口的类(Job1)的实例(j)本讲稿第二十八页,共五十八页 生成与运行线程方法2 classMyRunimplementsRunnablepublicvoidrun()线程体 MyRunmr=newMyRun();Threadt1=newThread(mr);t1.start();/Thread实例用于线程控制n适合于:定义run()方法的类必须是其他类或其他类的子类。本讲稿第二十九页,共五十八页方法之二:Runnable(续)n两种方法的选择当需要从其他类,如Applet类继承时,使用Runnable接口当编写简单的程序时,可考虑使用继承Thread类n例:RaceApplet
16、.java具体运行结果(线程调度)与平台有关本讲稿第三十页,共五十八页public class Runner extends Thread /赛跑者线程类 public int tick=1;public void run()while(tick 40000000)tick+;/Runner.java/RaceApplet是一个实现了多线程的Appletpublic class RaceApplet extends Applet implements Runnable final static int NUMRUNNERS=2;/定义赛跑线程的个数 final static int SPACI
17、NG=20;/声明两个赛跑线程 Runner runners=new RunnerNUMRUNNERS;/声明一个画图线程 Thread updateThread=null;本讲稿第三十一页,共五十八页 public void init()/重载Applet的init()方法 for(int i=0;i NUMRUNNERS;i+)runnersi=new Runner();/创建赛跑线程线程 runnersi.setPriority(i+1);/设优先级first=1,second=2 if(updateThread=null)/创建绘图线程,并设优先级为3 updateThread=new
18、 Thread(this,Thread Race);updateThread.setPriority(NUMRUNNERS+1);addMouseListener(new MyAdapter();/注册事件监听者 /end of init()本讲稿第三十二页,共五十八页 /内部事件监听者类,监听鼠标事件 class MyAdapter extends MouseAdapter /鼠标点击后,开始赛跑及绘制线程 public void mouseClicked(MouseEvent evt)if(!updateThread.isAlive()updateThread.start();/启动绘制线
19、程 for(int i=0;i NUMRUNNERS;i+)if(!runnersi.isAlive()runnersi.start();/启动赛跑线程 /end of class MyAdapter本讲稿第三十三页,共五十八页 public void paint(Graphics g)/paint()方法中绘制框架 /end of paint()/update()方法中绘制赛跑者的进度 public void update(Graphics g)for(int i=0;i NUMRUNNERS;i+)/画两条线 g.drawLine(SPACING,(i+1)*SPACING,SPACING
20、+(runnersi.tick)/100000,(i+1)*SPACING);/end of update()本讲稿第三十四页,共五十八页 public void run()/实现Runnable接口的run()方法 while(true)repaint();/重新绘制,自动调用update()方法 try Thread.sleep(10);/休眠,把执行机会让给低优先级线程 catch(InterruptedException e)/end of run()public void stop()/重载Applet的stop()方法 for(int i=0;i NUMRUNNERS;i+)if(
21、runnersi.isAlive()runnersi=null;/中止赛跑线程 if(updateThread.isAlive()updateThread=null;/中止绘图线程 /end of stop()/RaceApplet.java本讲稿第三十五页,共五十八页线程的同步与互斥n问题的提出多个线程执行的不确定性引起执行结果的不稳定如线程A:A1A2线程B:B1B2多个线程对内存、数据的共享,会造成操作的不完整性,会破坏数据。如push(a):i+;numi=a;pop():取出numi;i-;本讲稿第三十六页,共五十八页线程的同步与互斥n问题的解决同步:用synchronized关键字
22、前缀给针对共享资源的操作加锁;同步方法、同步块synchronizedvoidpush();synchronizedintpop();临界区实现机制:管程本讲稿第三十七页,共五十八页线程的同步与互斥n对象互斥锁在Java中,每个对象有一个“互斥锁”,该锁可用来保证在同一时刻只能有一个线程访问该对象。n锁的使用过程(当一个线程要操作一个对象时)准备加锁对象是否已加锁加锁进入临界区执行操作解锁否是本讲稿第三十八页,共五十八页线程的同步与互斥n加锁1(临界区-方法)synchronized方法名进入该方法时加锁n加锁2(临界区-代码块)方法名.synchronized(this)/进入该代码段时加锁
23、.n一个线程为某对象加锁后,便对该对象具有了监控权。本讲稿第三十九页,共五十八页线程的同步与互斥n线程间需协调与通讯:生产者/消费者问题进队出队生产者消费者本讲稿第四十页,共五十八页线程的同步与互斥nwait()与notify()Object类的方法:publicfinalvoidwait():令当前线程挂起并放弃管程,同步资源解锁,使别的线程可访问并修改共享资源,而当前线程排队等候再次对资源的访问notify()唤醒正在排队等待资源管程的线程中优先级最高者,使之执行并拥有资源的管程wait()+notify()+标志变量:可协调、同步不同线程的工作本讲稿第四十一页,共五十八页线程的同步与互斥
24、主线程线程1()线程2()操作对象共享数据(队)synchronized同步方法1(生产)wait()notify()synchronized同步方法2(消费)wait()notify()本讲稿第四十二页,共五十八页线程的同步与互斥 publicfinalvoidwait()方法n在当前线程中调用方法:对象名.wait()n使当前线程进入等待(某对象)状态,直到另一线程对该对象发出notify(或notifyAll)为止。n调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)n当前线程将释放对象监控权,然后进入等待队列(wait队列)。n在当前线程被notify后,要重新获得监控权,然
25、后从断点处继续代码的执行。本讲稿第四十三页,共五十八页线程的同步与互斥 publicfinalvoidnotify()方法n在当前线程中调用方法:对象名.notify()n功能:唤醒等待该对象监控权的一个线程。n调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)notifyAll()n唤醒wait队列中的所有线程,并把它门移入锁申请队列。本讲稿第四十四页,共五十八页线程状态新建状态就绪状态start()等待状态执行状态CPU调度run()结束消亡等待状态对象wait()池等待状态对象lock池wait()notify()synchronized()解锁 sleep()join()yi
26、eld()本讲稿第四十五页,共五十八页线程调度npublicstaticvoidsleep(longmillis)当前进程休眠指定时间npublicstaticvoidyield()主动让出CPU,重新排队正在执行的线程将CPU让给其他具有相同优先级的线程,自己进入就绪状态重新排队npublicfinalvoidjoin()等待某线程结束本讲稿第四十六页,共五十八页等待另一线程结束Runnableot=newotheeThread();Threadtt=newThread(ot);tt.start();/执行自己的工作trytt.join();catch(interruptedExceptio
27、ne)./继续做自己的事本讲稿第四十七页,共五十八页终止线程publicclassRimplementRunnableprivatebooleantimeToQuit=false;/设标记publicvoidrun()while(!timeToQuit)publicvoidstopRunning()timeToQuit=true;publicclasstestpublicstaticvoidmain(Stringargs)Runnabler=newR();Threadt=newThread(r);t.start();if()r.stopRunning();本讲稿第四十八页,共五十八页线程的同步
28、与互斥nWait_Notify程序CubbyHole.javan创建用户的线程子类Producer:产生数据(存数据);Consumer:消费数据(取数据)nCubbyHole类,共享数据区,同步方法put(intvalue)方法intget()方法n主类中创建共享数据对象,并启动两线程本讲稿第四十九页,共五十八页class CubbyHole private int seq;/共享数据 private boolean available=false;/条件标志变量 public synchronized int get()/取数据的同步方法get()while(available=false
29、)trywait();/条件不符合,则wait catch(InterruptedException e)available=false;/修改条件notify();/通知唤醒其他等待管程的线程return seq;/返回要取出的数值 /end of get()本讲稿第五十页,共五十八页/存放数据的同步方法put()public synchronized void put(int value)while(available=true)trywait();/条件不符合,则wait catch(InterruptedException e)seq=value;/把共享变量修改为要放置的数据avai
30、lable=true;/修改条件notify();/通知唤醒其他等待管程的线程 /end of put()/end of class CubbyHole本讲稿第五十一页,共五十八页class Producer extends Thread /生产者线程类 private CubbyHole cubbyhole;private int number;public Producer(CubbyHole c,int number)cubbyhole=c;this.number=number;public void run()/定义run()方法 for(int i=0;i 10;i+)/共产生10个
31、 cubbyhole.put(i);System.out.println(Producer#+this.number+put:+i);try sleep(int)(Math.random()*100);catch(InterruptedException e)/end of class Producer本讲稿第五十二页,共五十八页class Consumer extends Thread /消费者线程类 private CubbyHole cubbyhole;private int number;public Consumer(CubbyHole c,int number)cubbyhole=
32、c;this.number=number;public void run()/定义run()方法 int value=0;for(int i=0;i 10;i+)/消费10个 value=cubbyhole.get();System.out.println(Consumer#+this.number+got:+value);/end of class Consumer本讲稿第五十三页,共五十八页class ProducerConsumerTest /主类:测试 public static void main(String args)CubbyHole c=new CubbyHole();/th
33、e shared data object Producer p1=new Producer(c,1);/Producer线程 Consumer c1=new Consumer(c,1);/Consumer线程 p1.start();/启动生产者线程 c1.start();/启动消费者线程 /end of ProducerConsumerTest程序执行结果:生产者线程和消费者线程严格地轮流执行,获得了线程间的协调执行。本讲稿第五十四页,共五十八页线程的死锁n死锁不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁n解决方法专门的算法、原则尽量减少同步资源的定义本讲稿第五十五页,共五十八页思考n1.什么是线程?它和进程有什么区别?适用方向是什么?n2.Java的线程是如何实现的?n3.Java的线程是如何调度的?n4.Java中的多线程有什么特点?同步和互斥的原理是如何实现的?本讲稿第五十六页,共五十八页n作业:P3649.11,9.12n补充题:编程用两种方法实现多线程。本讲稿第五十七页,共五十八页下课!本讲稿第五十八页,共五十八页
限制150内