Java语言程序设计第8章.ppt_第1页
Java语言程序设计第8章.ppt_第2页
Java语言程序设计第8章.ppt_第3页
Java语言程序设计第8章.ppt_第4页
Java语言程序设计第8章.ppt_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章线程,郑莉,JAVA语言程序设计,2,本讲内容,线程基础线程的概念Thread类Runnable接口资源共享和线程同步线程间的通信线程的生命周期线程的优先级程序举例,3,线程的概念,进程:程序的一次执行线程:一个进程中的多个控制流通过多线程,一个进程表面上看同时可以执行一个以上的任务并发多数程序设计语言不支持并发,支持多线程要借助于操作系统“原语(primitives)”Java是第一个支持内置线程操作的主流编程语言,线程基础,4,Thread类简介,线程类需要继承Thread类Thread的构造函数publicThread(StringthreadName)publicThread()在线程的run方法中编写线程的主要任务sleep方法使线程休眠interrupt方法中断一个运行中的线程isAlive方法检查线程的状态setName方法设置线程名join方法等待线程结束,以执行当前线程,线程基础,5,例8_1在新线程中计算整数的阶乘,publicclassEx8_1publicstaticvoidmain(Stringargs)System.out.println(mainthreadstarts);FactorialThreadthread=newFactorialThread(10);thread.start();System.out.println(newthreadstarted,mainthreadends);/endmain,线程基础,/classFactorialThreadcontrolsthreadexecutionclassFactorialThreadextendsThreadprivateintnum;publicFactorialThread(intnum)this.num=num;publicvoidrun()inti=num;intresult=1;while(i0)result=result*i;i=i-1;System.out.println(Thefactorialof+num+is+result);System.out.println(newthreadends);,运行结果如下:mainthreadstartsnewthreadstarted,mainthreadendsThefactorialof10is3628800newthreadends,8,例8_2创建3个新线程,每个线程睡眠任意0-6秒钟,然后结束。,publicclassEx8_2publicstaticvoidmain(Stringargs)/创建并命名每个线程TestThreadthread1=newTestThread(thread1);TestThreadthread2=newTestThread(thread2);TestThreadthread3=newTestThread(thread3);System.out.println(Startingthreads);thread1.start();/启动线程1thread2.start();/启动线程2thread3.start();/启动线程3System.out.println(Threadsstarted,mainendsn);,线程基础,classTestThreadextendsThreadprivateintsleepTime;publicTestThread(Stringname)/构造函数super(name);/调用基类构造函数为线程命名/获得随机休息毫秒数sleepTime=(int)(Math.random()*6000);publicvoidrun()/线程启动并开始运行后要执行的方法trySystem.out.println(getName()+goingtosleepfor+sleepTime);Thread.sleep(sleepTime);/线程休眠catch(InterruptedExceptionexception);/运行结束,给出提示信息System.out.println(getName()+finished);,运行结果为:StartingthreadsThreadsstarted,mainendsthread1goingtosleepfor3519thread2goingtosleepfor1689thread3goingtosleepfor5565thread2finishedthread1finishedthread3finished,11,Runnable接口,如果希望一个已经有基类的类支持多线程,则不能再继承Thread类了(Java不支持多继承)解决方法:使类实现Runnable接口,再与Thread类结合使用一个内部类提供Runnable的实现代码,将内部类的对象与Thread结合相对于Thread类,它更适合于多个线程处理同一资源,线程基础,12,例8_3使用Runnable接口实现例8_1功能,publicclassEx8_1publicstaticvoidmain(Stringargs)System.out.println(mainthreadstarts);FactorialThreadt=newFactorialThread(10);newThread(t).start();System.out.println(newthreadstarted,mainthreadends);/endmain,线程基础,/classFactorialThreadcontrolsthreadexecutionclassFactorialThreadimplementsRunnableprivateintnum;publicFactorialThread(intnum)this.num=num;publicvoidrun()inti=num;intresult=1;while(i0)result=result*i;i=i-1;System.out.println(Thefactorialof+num+is+result);System.out.println(newthreadends);,14,例8_4使用Runnable接口实现例8_2功能,publicclassEx8_4publicstaticvoidmain(Stringargs)/创建3个实现Runnable接口类的对象TestThreadthread1=newTestThread();TestThreadthread2=newTestThread();TestThreadthread3=newTestThread();System.out.println(Startingthreads);/分别以三个对象为参数创建三个新线程,/第二个参数为新线程命名并启动之newThread(thread1,Thread1).start();newThread(thread2,Thread2).start();newThread(thread3,Thread3).start();System.out.println(Threadsstarted,mainendsn);,线程基础,classTestThreadimplementsRunnableprivateintsleepTime;publicTestThread()/构造方法/获得随机休息毫秒数sleepTime=(int)(Math.random()*6000);publicvoidrun()/线程启动并开始运行后要执行的方法trySystem.out.println(Thread.currentThread().getName()+goingtosleepfor+sleepTime);Thread.sleep(sleepTime);/线程休眠catch(InterruptedExceptionexception);/运行结束,给出提示信息System.out.println(Thread.currentThread().getName()+finished);,运行结果如下:StartingthreadsThread1goingtosleepfor1487Thread2goingtosleepfor1133Threadsstarted,mainendsThread3goingtosleepfor2328Thread2finishedThread1finishedThread3finished,17,资源共享和线程同步,独立的同时运行的线程有时需要共享一些数据并且考虑到彼此的状态和动作。例如生产/消费问题:生产线程产生数据流,然后这些数据流再被消费线程消费。具体来说,假设一个Java应用程序,其中有一个线程负责往文件写数据,另一个线程从同一个文件中往出都数据,因为涉及到同一个资源,这里是同一个文件,这两个线程必须保证某种方式的同步。当多个线程的执行代码来自同一个类的实例(若干个)时,即称它们共享相同的代码,当共享访问相同的对象时,即它们共享相同的数据。使用Runnable接口可以轻松实现多个线程共享相同数据,只要用同一个实现了Runnable接口的实例作为参数创建多个线程就可以了。,线程基础,18,例8_5修改例8_4,/只用一个Runnable类型的对象为参数创建3个新线程。publicclassEx8_5publicstaticvoidmain(Stringargs)/只创建1个实现Runnable接口类的对象TestThreadthread=newTestThread();System.out.println(Startingthreads);/只用一个Runnable类型对象为参数创建三个新线程,/命名并启动之newThread(thread,Thread1).start();newThread(thread,Thread2).start();newThread(thread,Thread3).start();System.out.println(Threadsstarted,mainendsn);,线程基础,classTestThreadimplementsRunnableprivateintsleepTime;publicTestThread()/构造函数/获得随机休息毫秒数sleepTime=(int)(Math.random()*6000);publicvoidrun()/线程启动并开始运行后要执行的方法trySystem.out.println(Thread.currentThread().getName()+goingtosleepfor+sleepTime);Thread.sleep(sleepTime);/线程休眠catch(InterruptedExceptionexception);/运行结束,给出提示信息System.out.println(Thread.currentThread().getName()+finished);,StartingthreadsThread1goingtosleepfor966Thread2goingtosleepfor966Threadsstarted,mainendsThread3goingtosleepfor966Thread1finishedThread2finishedThread3finished,21,例8_6用三个线程模拟三个售票口,总共出售200张票。,publicclassEx8_6publicstaticvoidmain(Stringargs)/新建一个售票类的对象SellTicketst=newSellTickets();/用此对象作为参数创建3个新线程并启动newThread(t).start();newThread(t).start();newThread(t).start();,线程基础,classSellTicketsimplementsRunnable/将共享的资源作为私有变量privateinttickets=200;publicvoidrun()while(tickets0)/直到没有票可售为止System.out.println(Thread.currentThread().getName()+issellingticket+tickets-);,23,例8_7用两个线程模拟存票、卖票过程,publicclassEx8_7publicstaticvoidmain(Stringargs)/新建一个票类对象,总票数作为参数Ticketst=newTickets(10);/以票类对象为参数创建存票线程对象,并启动newProducer(t).start();/以同一个票类对象为参数创建售票线程,并启动newConsumer(t).start();,线程基础,classTickets/票类intnumber=0;/票号intsize;/总票数/表示目前是否有票可售booleanavailable=false;/构造方法,传入总票数参数publicTickets(intsize)this.size=size;,classProducerextendsThread/存票线程Ticketst=null;publicProducer(Ticketst)/构造函数以一个票类对象为参数this.t=t;publicvoidrun()/限制循环条件为存票序号小于总票数while(t.number)t.size)System.out.println(Producerputsticket+(+t.number);t.available=true;/可以卖票,classConsumerextendsThread/售票线程Ticketst=null;inti=0;publicConsumer(Ticketst)/构造函数以一个票类对象为参数this.t=t;publicvoidrun()while(it.size)/循环条件为售票序号小于总票数if(t.available=true,运行结果Producerputsticket1Producerputsticket2Producerputsticket3Producerputsticket4Producerputsticket5Producerputsticket6Producerputsticket7Producerputsticket8Consumerbuysticket1Consumerbuysticket2Consumerbuysticket3Consumerbuysticket4Consumerbuysticket5Consumerbuysticket6Consumerbuysticket7Consumerbuysticket8Producerputsticket9Producerputsticket10死机(进入死循环),28,错误原因,假如售票线程运行到t.available=false之前,CPU切换到执行存票线程,存票线程将available置为true,但再次切换到售票线程后,售票线程执行t.available=false,则由于售票号目前还是8,小于总票数,且存票线程已经结束不再能将t.available置为true,则售票线程陷入了死循环。,线程基础,29,线程同步(Synchronization),Java使用的同步机制是监视器,支持线程的互斥与同步互斥:许多线程在同一个共享数据上操作而互不干扰,同一时刻只能有一个线程访问该共享数据。因此有些方法或程序段在同一时刻只能被一个线程执行,称之为监视区。协作:多个线程可以有条件地同时操作共享数据执行监视区代码的线程在条件满足的情况下可以允许其它线程进入监视区。,线程基础,30,线程间的通信,线程同步关键字synchronized用于指定需要同步的代码段或方法,也就是监视区。wait()当前状态不适合本线程执行时,进入等待状态notify()随机唤醒一个等待的线程,本线程继续执行。notifyAll()唤醒所有等待的线程,本线程继续执行。,线程基础,31,线程间的通信,线程被唤醒以后,还要等发出唤醒消息者释放监视器,这期间关键数据仍可能被改变。被唤醒线程的线程可能有多个。(使用notifyAll时)。被唤醒的线程开始执行时,一定要判断当前状态是否适合自己运行。,线程基础,32,例8_8实现例8_7功能。,将同步方法放在共享的资源类Tickets中。publicclassEx8_8publicstaticvoidmain(Stringargs)Ticketst=newTickets(10);newProducer(t).start();newConsumer(t).start();,线程基础,classTicketsintsize;/票总数intnumber=0;/存票序号inti=0;/售票序号booleanavailable=false;/是否有待售的票publicTickets(intsize)this.size=size;publicsynchronizedvoidput()/同步代码块,实现存票的功能System.out.println(Producerputsticket+(+number);available=true;publicsynchronizedvoidsell()/同步代码块,实现售票的功能if(available=true,classConsumerextendsThreadTicketst=null;/构造方法,使两线程共享票类对象publicConsumer(Ticketst)this.t=t;publicvoidrun()/如果售票数小于限定总量,则不断售票while(t.it.size)t.sell();,35,例8_9每存入一张票,就售一张票,售出后,再存入,publicclassEx8_8publicstaticvoidmain(Stringargs)Ticketst=newTickets(10);newProducer(t).start();newConsumer(t).start();,线程基础,classTicketsintsize;intnumber=0;inti=0;booleanavailable=false;publicTickets(intsize)this.size=size;publicsynchronizedvoidput()if(available)/如果还有存票待售,则存票线程等待trywait();catch(Exceptione)System.out.println(Producerputsticket+(+number);available=true;notify();./存票后唤醒售票线程开始售票,publicsynchronizedvoidsell()if(!available)/如果没有存票,则售票线程等待trywait();catch(Exceptione)if(i=number)System.out.println(Consumerbuysticket+(+i);if(i=number)tryThread.sleep(1);catch(Exceptione)available=false;notify();/售票后唤醒存票线程开始存票,classProducerextendsThreadTicketst=null;publicProducer(Ticketst)this.t=t;publicvoidrun()while(t.numbert.size)t.put();,classConsumerextendsThreadTicketst=null;publicConsumer(Ticketst)this.t=t;publicvoidrun()while(t.it.size)t.sell

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论