




已阅读5页,还剩61页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
7.Java多线程,2019/12/18,2,内容,多线程基本概念Java多线程创建多线程线程的状态控制Java多线程的一些问题小结注:本课件部分材料来自网络,2019/12/18,3,1多线程基本概念,文件,输入输出装置,各种系统资源,数据区段,程序区段,只有一个地方在执行,文件,输入输出装置,各种系统资源,程序区段,同时有数个地方在执行,传统的进程,多线程的任务,2019/12/18,4,多线程的优势:减轻编写交互频繁、涉及面多的程序的困难程序的吞吐量会得到改善由多个处理器的系统,可以并行运行不同的线程(否则,任何时刻只有一个线程在运行,形成并发运行),2019/12/18,5,线程与进程的区别:多个进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能互相影响线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小,多线程编程原则,安全性:如果两个以上的线程访问同一对象时,一个线程会损坏另一个线程的数据,这就违反了安全性原则可行性:如果仅仅实现了安全性,程序却在某一点后不能继续执行或者多个线程发生死锁,那么这样的程序也不能作为真正的多线程程序来应用高性能:多线程的目的是为了增加程序运行的性能,2019/12/18,6,2019/12/18,7,2.Java线程概念,对线程的综合支持是Java技术的一个重要特色.它提供了thread类、监视器和条件变量的技术.虽然许多操作系统支持多线程,但若要用C或C+编写多线程程序是十分困难的,因为它们对数据同步的支持不充分.,线程对象和线程的区别:线程对象是可以产生线程的对象比如在java平台中Thread对象,Runnable对象。线程,是指正在执行的一个指令序列。在java平台上是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。,2019/12/18,8,思考如果我们成功编译了该java文件,然后运行发生的过程Jvm进程启动,JVM产生一个主线程还有一些其它线程,例如垃圾回收等,2019/12/18,9,classBeginClasspublicstaticvoidmain(Stringargs)for(inti=0;i100;i+)System.out.println(Hello,World!);,剖析多线程程序,2019/12/18,10,classMyThreadextendsThreadpublicvoidrun()System.out.println(Threadsay:Hello,World!);publicclassMoreThreadspublicstaticvoidmain(Stringargs)newMyThread();newMyThread().start();System.out.println(Mainsay:Hello,World);,2019/12/18,11,3.创建多线程,Runnable与Thread1.publicclassmythreadextendsAppletimplementsRunnable(小应用或已经是某个类的子类时)2.继承类ThreadpublicclassmythreadextendsThread创建方法:newthread=newThread(this);newthread.start();,2019/12/18,12,Runable与Thread的区别使用runable最主要的原因是:java缺少多重继承的机制,可能你的类已经继承了其他类了,这时你无法继承自thread类,只能用runnable了Runable创建的线程共享数据区,publicclassTestpublicstaticvoidmain(Stringargs)throwsExceptionMyThreadmt=newMyThread();mt.start();mt.join();Thread.sleep(3000);mt.start();输出:Exceptioninthreadmainjava.lang.IllegalThreadStateException说明:通过Thread实例的start(),一个Thread的实例只能产生一个线程,2019/12/18,13,2019/12/18,14,classRimplementsRunnableprivateintx=0;publicvoidrun()for(inti=0;i100;i+)tryThread.sleep(10);catch(Exceptione)System.out.println(x+);,publicclassTestpublicstaticvoidmain(Stringargs)throwsExceptionRr=newR();for(inti=0;i10;i+)newThread(r).start();,2019/12/18,15,packagedebug;importjava.io.*;importjava.lang.Thread;classMyThreadextendsThreadpublicintx=0;publicvoidrun()System.out.println(+x);classRimplementsRunnableprivateintx=0;publicvoidrun()System.out.println(+x);,publicclassTestpublicstaticvoidmain(Stringargs)throwsExceptionfor(inti=0;i10;i+)Threadt=newMyThread();t.start();Thread.sleep(10000);/让上面的线程运行完成Rr=newR();for(inti=0;i10;i+)Threadt=newThread(r);t.start();,2019/12/18,16,重要的方法,start()从CPU中申请另一个线程空间来执行run()方法中的代码run()是运行线程的主体,启动线程时,由java直接调用publicvoidrun()如果你不调用Start,直接调用run,会如何?stop()停止线程,调用线程的newthread.stop()(不是安全的处理)sleep方法暂停线程的执行,让其它线程得到机会,sleep要丢出异常,必须抓住:Trysleep(100)catch(InterruptedExceptione),2019/12/18,17,importjavax.swing.*;publicclassApplet1extendsJAppletmythreadt1=newmythread();publicvoidinit()t1.start();classmythreadextendsThreadpublicvoidrun()for(inti=0;i4;i+)System.out.println(+i);trysleep(400);catch(InterruptedExceptione),2019/12/18,18,7.2创建线程的方式,importjavax.swing.*;importjava.awt.*;publicclassApplet1extendsJAppletCt1=newC(this);publicvoidinit()t1.start();publicvoidpaint(Graphicsg)g.drawString(Hello,java,10,50);classCextendsThreadApplet1a;C(Applet1b)a=b;publicvoidrun()while(true)a.repaint();trysleep(400);catch(InterruptedExceptione),join:等待线程执行完毕,被等待的那个线程不结束,当前线程就一直等待.,2019/12/18,19,publicclassTestpublicstaticvoidmain(Stringargs)throwsExceptionMyThreadmt=newMyThread();mt.start();mt.join();System.out.println(101);,2019/12/18,20,其它常用的方法isAlive:判断线程目前是否正在执行状态中if(newthread.isAlive()newthread.stop();resume:要求被暂停线程继续执行suspend:暂停线程的执行yield:将执行的权力交给其它线程,自己到队列的最后等待.,2019/12/18,21,线程的优先权某一时刻只有一个线程在执行,调度策略为固定优先级调度.newthread.setPriority(Thread.MIN_PRIORITY)级别有:MIN-PRIORITYNOM_PRIORITYMAX-PRIORITY自私的线程:有很高的优先权的线程,不主动睡眠或让出处理器控制权.,2019/12/18,22,4.线程的状态控制,线程的状态,2019/12/18,23,当一个线程执行完所有语句后就自动终止调用线程的stop()方法,也可以强制终止线程,可能产生不完整的残废数据。如果希望线程正常终止,可采用标记来使线程中的run()方法退出,2019/12/18,24,publicclassXyzimplementsRunnableprivatebooleantimeToQuit=false;publicvoidrun()while(!timeToQuit)./cleanupbeforerun()ends;publicvoidstopRunning()timeToQuit=true;,2019/12/18,25,publicclassControlThreadprivateRunnabler=newXyz();privateThreadt=newThread(r);publicvoidstartThread()t.start();publivoidstopThread()r.stopRunning();,2019/12/18,26,暂停线程的执行等待条件满足再执行下面的例子显示线程的挂起和唤醒Applet第一次开始时,线程被启动浏览器改变页面时,小应用程序的stop()方法被调用,线程被挂起.浏览器回到原来的页面时,线程被唤醒.,2019/12/18,27,publicvoidstart()if(mythread=null)mythread=newThread();mythread.start();elsemythread.resume();publicvoidrun()while(true)trysleep(100);catch(InterruptedExceptione)publicvoidstop()mythread.suspend();.,2019/12/18,28,5.Java多线程问题,执行顺序多个线程运行时,调度策略为固定优先级调度.级别相同时,由操作系统按时间片来分配下面给出的例子中,共运行三个线程,它们做同样的事,每次打印循环次数和自己的序列号,运行结果表明,它们并不是连续运行的.如果给某个线程赋予较高的优先权,则发现这个进程垄断控制权thread.setPriority(Thread.MAX_PRIORITY),2019/12/18,29,7.3多线程问题,/多个进程运行时执行顺序是交叉的publicclassMyThreadextendsThreadintthreadNum;publicstaticvoidmain(Stringargs)MyThreadarray=newMyThread3;for(inti=0;i);trysleep(1000);catch(InterruptedExceptione);System.out.println(thread+threadNum+bye.);,2019/12/18,30,如何写多线程,1.分别定义不同的线程类,在各自的run方法中定义线程的工作classmythread1extendsThreadpublicvoidrun.classmythread2extendsThreadpublicvoidrun.2.在主类中实例化各线程类,并启动线程.publicclassdemoextendsAppletpublicvoidinit()mythreadt1=newmythread1();mythreadt2=newmythread2();t1.start();t2.start();,2019/12/18,31,练习:将窗口分为上下两个区,分别运行两个线程,一个在上面的区域中显示由右向左游动的字符串,另一个在下面的区域从左向右游动的字符串.方法一:一个线程,在paint方法中使用两个输出字符串的语句publicvoidpaint(Graphicsg)ify1200y2=0elsey2=y2+10;g.drawString(“hello,Java!”,20,y1,);g.drawString(“hello,Java!”,40,y2,);,2019/12/18,32,方法二:定义两个类,运行各自的线程,各自有自己的paint()方法.注意:两个Applet必须是panel类或者是canvas类,将Applet的区域分成两块,否则不能运行paint语句.,2019/12/18,33,importjavax.swing.*;importjava.awt.*;publicclassApplet1extendsJAppletCt1,t2;myCanvasc1,c2;ContainercontentPane=getContentPane();publicvoidinit()c1=newmyCanvas();c2=newmyCanvas();contentPane.setLayout(newGridLayout(2,1);contentPane.validate();contentPane.add(c1);contentPane.add(c2);t1=newC(c1,5);t2=newC(c2,-5);t1.start();t2.start();,classmyCanvasextendsCanvaspublicvoidpaint(Graphicsg,intx,inty)g.drawString(HelloWorld,x,y);classCextendsThreadmyCanvasa;intsteps;intx;C(myCanvasb,intsize)a=b;steps=size;x=0;publicvoidrun()while(true)x=x+steps;if(xa.getWidth()x=0;a.repaint();a.paint(a.getGraphics(),x,50);trysleep(10);catch(InterruptedExceptione),2019/12/18,34,线程间的通信,1.线程间的通信可以用管道流,.创建管道流:PipedInputStreampis=newPipedInputStream();PipedOutputStreampos=newPipedOutputStream(pis);或:PipedOutputStreampos=newPipedOutputStream();PipedInputStreampis=newPipedInputStream(pos);,2019/12/18,35,管道流不能直接读写PrintStreamp=newPrintStream(pos);p.println(“hello”);DataInputStreamd=newDataInputStream(pis);d.readLine();2.通过一个中间类来传递信息.,2019/12/18,36,管道流可以连接两个线程间的通信两个线程在运行,一个往外输出信息,一个读入信息.将一个写线程的输出通过管道流定义为读线程的输入.outStream=newPipedOutputStream();inStream=newPipedInputStream(outStream);newWriter(outStream).start();newReader(inStream).start();,2019/12/18,37,主类Pipethread,辅类Writer线程类,辅类Reader线程类,管道流,将数据写到输出流,从流中读数据,输入流,作为参数传给WriterWriter(outStream),2019/12/18,38,7.4多线程问题-线程间的通信,.,importjava.io.*;publicclassPipethreadpublicstaticvoidmain(Stringargs)PipethreadthisPipe=newPipethread();thisPcess();publicvoidprocess()PipedInputStreaminStream;PipedOutputStreamoutStream;PrintStreamprintOut;tryoutStream=newPipedOutputStream();inStream=newPipedInputStream(outStream);newWriter(outStream).start()newReader(inStream).start();catch(IOExceptione),2019/12/18,39,7.4多线程问题-线程间的通信,classReaderextendsThreadprivatePipedInputStreaminStream;publicReader(PipedInputStreami)inStream=i;publicvoidrun()Stringline;DataInputStreamd;booleanreading=true;d=newDataInputStream(inStream);while(reading,2019/12/18,40,7.4多线程问题-线程间的通信,.,classWriterextendsThreadprivatePipedOutputStreamoutStream;privateStringmessages=Monday,Tuesday,Wednsday,Thursday,Friday:,Saturday:,Sunday:;publicWriter(PipedOutputStreamo)outStream=o;publicvoidrun()PrintStreamp=newPrintStream(outStream);for(inti=0;imessages.length;i+)p.println(messagesi);p.flush();System.out.println(WrIte:+messagesi);tryThread.sleep(4000);catch(InterruptedExceptione);p.close();p=null;,2019/12/18,41,结果可能是:,WrIte:MondayRead:MondayWrIte:TuesdayRead:TuesdayRead:WednsdayWrIte:WednsdayRead:ThursdayWrIte:ThursdayRead:Friday:WrIte:Friday:WrIte:Saturday:Read:Saturday:Read:Sunday:WrIte:Sunday:,资源协调,2019/12/18,42,2019/12/18,43,资源协调,2019/12/18,44,对共享对象的访问必须同步,叫做条件变量.Java语言允许通过监视器(有的参考书称其为管程)使用条件变量实现线程同步.监视器阻止两个线程同时访问同一个条件变量.它如同锁一样作用在数据上.线程1进入withdrawal方法时,获得监视器(加锁);当线程1的方法执行完毕返回时,释放监视器(开锁),线程2的withdrawal方能进入.,2019/12/18,45,用synchronized来标识的区域或方法即为监视器监视的部分。一个类或一个对象有一个监视器,如果一个程序内有两个方法使用synchronized标志,则他们在一个监视器管理之下.一般情况下,只在方法的层次上使用关键区,2019/12/18,46,此处给出的例子演示两个线程在同步限制下工作的情况.classAccountstaticsintbalance=1000;staticsintexpense=0;publicsynchronizedvoidwithdrawl(intamount)if(amount=balance)balance-=amount;expense+=amount;elseSystem.out.println(“bounced:“+amount);,实例范围同步方法publicdclasssyncTestsynchronizedvoidaMethod()/需要同步使用的代码synchronizedaMethod()可以防止多个线程同时访问这个对象实例的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。,2019/12/18,47,实例范围同步区块publicdclasssyncTestvoidaMethod()/无需同步使用的代码synchronized(this)/需要同步使用的代码块除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是:synchronized(this)/*区块*/,它的作用域是当前对象。,2019/12/18,48,类范围在类范围内使用synchronized也有同步方法和同步区块两种形式:类范围同步方法publicdclasssyncTestsynchronizedstaticvoidaMethod()/需要在类范围同步使用的代码,2019/12/18,49,synchronizedstaticaStaticMethod防止多个线程同时访问这个类中的synchronizedstatic方法。它可以对类的所有对象实例起作用。也就是说在一个JVM中,同一时间最多有一个该类的静态同步方法在执行。这样的方法可以应用到多线程的同步中,实现各线程直接的数据共享和互动,2019/12/18,50,类范围同步区块publicdclasssyncTeststaticvoidaMethod()/无需同步使用的代码synchronized(syncTest.class)/需要在类范围同步使用的代码类范围同步区块功能与类范围同步方法相同,只是对一个区块的代码的同步。用法是:在static方法内加同步区块:sychronized(类名.class)/*区块*/。,2019/12/18,51,synchronized关键字是不能继承的,也就是说,基类的方法synchronizedf()在继承类中并不自动是synchronizedf(),而是变成了f()。继承类需要你显式的指定它的某个方法为synchronized方法;,2019/12/18,52,2019/12/18,53,2.等待同步数据,可能出现的问题:生产者比消费者快时,消费者会漏掉一些数据没有取到消费者比生产者快时,消费者取相同的数据.notify()和wait()方法用来协调读取的关系.notify()和wait()都只能从同步方法中的调用.,2019/12/18,54,notify的作用是唤醒正在等待同一个监视器的线程.wait的作用是让当前线程等待信息版例子read()方法在读信息之前先等待,直到信息可读,读完后通知要写的线程.write()方法在写信息之前先等待,直到信息被取走,写完后通知要读的进程.,2019/12/18,55,writer,reader,aaaa,bbbbb,cccc,aaaa,aaaa,aaaa,aaaa,aaaa,aaaa,bbbbb,cccc,cccc,cccc,cccc,bbbbb,cccc,2019/12/18,56,publicclassWaitNotifyDemopublicstaticvoidmain(Stringargs)MessageBoardm=newMessageBoard();Readerreadfrom_m=newReader(m);Writerwriteto_m=newWriter(m);writeto_m.start();readfrom_m.start();,2019/12/18,57,7.3多线程问题-资源协调,classMessageBoardprivateStringmessage;privatebooleanready=false;publicsynchronizedStringread()while(ready=false)trywait();catch(InterruptedExceptione)ready=false;notify();returnmessage;publicsynchronizedvoidwrite(Strings)while(ready=true)trywait();catch(InterruptedExceptione)message=s;System.out.println(BoadGot:+s);ready=true;notify();,2019/12/18,58,7.3多线程问题-资源协调,classReaderextendsThreadprivateMessageBoardmBoard;publicReader(MessageBoardm)mBoard=m;publicvoidrun()Strings=;booleanreading=true;while(reading)s=mBoard.read();System.out.println(Readerread:+s);if(s.equals(logoff)reading=false;System.out.println(Finished:10seconds.);trysleep(10000);catch(InterruptedExceptione),2019/12/18,59,7.3多线程问题-资源协调,classWriterextendsThreadprivateMessageBoardmBoard;privateStringmessages=Monday:-,.,Sunday:-;publicWriter(MessageBoardm)mBoard=m;publicvoidrun()for(i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高中史记选读课件
- 高中化学氧气课件
- 纺织服装行业市场前景及投资研究报告:研究分析方法
- 2025-2026学年人教精通版(2024)英语四年级上册全册(教案)教学设计
- 吊盘信号工岗位责任与应急处理能力合同
- 离婚子女抚养权争夺案件调解与心理辅导合同
- 离婚协议书制作要点及财产分割与子女抚养参考
- 园艺分享花卉经验
- 职业教育学生技能训练指导方案细则
- 心理素质的塑造和提升方案
- 委托寺庙管理经营协议书
- 三人茶楼合伙合同范本
- T/CCS 026-2023煤矿防爆锂电池车辆动力电源换电安全技术要求
- 新药研究与开发技术 课件2.新药的发现研究
- 中医调理男女生殖系统疾病的技巧
- 2025年湖北国土资源职业学院单招职业技能测试题库必考题
- 2024年设备监理师历年真题答案
- 杜绝“死亡游戏”(梦回大唐)主题班会教学设计上学期-高中主题班会
- 盾构施工安全管理
- 职场动物进化手册
- 2025中国农业银行贷款合同
评论
0/150
提交评论