博学谷——让IT教学更简单,让IT学习更有效1第五章补充案例案例5-1继承Thread类创建多线程一、案例描述1、考核知识点编号:00105002名称:继承Thread类创建多线程2、练习目标掌握如何通过继承Thread类实现多线程的创建。掌握Thread类中run()方法和start()方法的使用。3、需求分析在程序开发中,会遇到一个功能需要多个线程同时执行才能完成的情况。这时,可以通过继承线程类Thread,并重写Thread类中的run()方法来实现。为了让初学者熟悉如何创建多线程,在案例中将通过继承Thread类方式创建线程,并实现多线程分别打印0~99的数字的功能。4、设计思路(实现原理)1)自定义一个类Demo,使其继承Thread类。2)在Demo类中重写run()方法,在run()方法内编写一个for循环,循环体内打印:“Demo:”+当前循环次数。3)编写测试类Example01,在Example01类的main()方法中,创建一个Demo对象,并执行其start()方法,接着编写一个for循环,循环体内打印:“main:”+当前循环次数。二、案例实现classDemoextendsThread{publicvoidrun(){for(intx=0;x100;x++){System.out.println(Demo:+x);}}}publicclassExample01{publicstaticvoidmain(String[]args){Demod=newDemo();d.start();for(intx=0;x100;x++){System.out.println(main:+x);}博学谷——让IT教学更简单,让IT学习更有效2}}运行结果如图5-1所示。图5-1运行结果三、案例总结1、通过继承Thread类,并重写Thread类中的run()方法可以实现多线程。2、Thread类中,提供的start()方法用于启动新线程,线程启动后,系统会自动调用run()方法。3、main()方法中有一条主线程在运行。案例5-2实现Runnable接口创建多线程一、案例描述1、考核知识点编号:00105003名称:实现Runnable接口创建多线程2、练习目标掌握如何通过实现Runnable接口方式创建多线程。掌握如何使用Thread类的有参构造方法创建Thread对象。3、需求分析在Java中只支持单继承,因此通过继承Thread类创建线程有一定的局限性,这时可以使用另一种方式,即实现Runnable接口来创建线程。通过这种方式需要在Thread(Runnabletarget)的构造方法中,传递一个实现了Runnable接口的实例对象。接下来在案例中将通过实现Runnable接口方式创建线程,并实现多线程分别打印0~99的数字的功能。4、设计思路(实现原理)1)自定义一个类Demo,使其实现Runnable接口。2)在Demo类中覆写run()方法,在方法编写一个for循环,循环体内打印:当前线程名称:+当前循环次数。3)编写测试类Example02,在Example02类的main()方法中,创建一个Demo对象,利用Thread(Runnabletarget)构造方法创建2个线程对象,分别命名为“蜘蛛侠”和“钢铁侠”,并执行线程对象的start()方法,同时编写for循环,循环内打印“main:”+当前循环次数。博学谷——让IT教学更简单,让IT学习更有效3二、案例实现classDemoimplementsRunnable{publicvoidrun(){for(intx=0;x100;x++){System.out.println(Thread.currentThread().getName()+:+x);}}}publicclassExample02{publicstaticvoidmain(String[]args){Demod=newDemo();Threadt1=newThread(d,蜘蛛侠);Threadt2=newThread(d,钢铁侠);t1.start();t2.start();for(intx=0;x100;x++){System.out.println(main:+x);}}}运行结果如图5-2所示。图5-2运行结果三、案例总结1、可以把实现了Runnable接口并重写run()方法的实例对象,作为Thread有参构造方法的参数来创建多线程程序。2、使用Thread类的构造方法Thread(Runnabletarget,Stringname)创建线程对象时,还可以给线程指定新名称。3、思考一下:既然有了继承Thread类的方式,为什么还要有实现Runnable接口的方式?a)可以避免由于Java的单继承带来的局限性。在开发中经常碰到这样一种情况,就是使用一个已经继承了某一个类的子类创建线程,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么就只能采用实现Runnable接口的方式。博学谷——让IT教学更简单,让IT学习更有效4b)实现接口的方式,适合多个相同程序代码的线程去处理同一个资源的情况,把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想。例如:一个售票程序继承了Thread类,在售票时启动了多个售票程序,但他们不是同一个对象,数据没有共享,这样就会出现票数重复出售的情况;而当售票程序实现Runnable接口后,多个线程运行同一个售票程序,实现了票数共享的好处。案例5-3设置后台线程一、案例描述1、考核知识点编号:00105005名称:后台线程2、练习目标了解后台线程的生命周期掌握如何将线程设置为后台线程3、需求分析默认情况下,新创建的线程都是前台线程,若想使前台线程变为后台线程,可以使用setDaemon(true)方法实现,为了让初学者熟悉后台线程,案例中将通过设置一个后台线程并演示后台线程和程序结束之间的关系。4、设计思路(实现原理)1)自定义一个类Watcher,使其实现Runnable接口。2)在Watcher类中覆写run()方法,在方法内编写一个for循环,循环体内打印:线程名称+循环次数。3)编写测试类Example03,在Example03类的main()方法中,创建一个Watcher对象,利用Thread(Runnabletarget)构造方法创建线程对象并命名,将线程设置为后台线程,执行该线程的start()方法,接着编写一个for循环,循环内打印循环次数。二、案例实现classWatcherimplementsRunnable{publicvoidrun(){for(intx=0;x1000;x++){System.out.println(我是+Thread.currentThread().getName()+守护者,+我在守护雅典娜+x);}}}publicclassExample03{publicstaticvoidmain(String[]args){Watcherwatcher=newWatcher();Threadt=newThread(watcher,星矢);t.setDaemon(true);博学谷——让IT教学更简单,让IT学习更有效5t.start();for(inti=3;i0;i--){System.out.println(我是雅典娜女神,我马上死了!+i);if(i==1){System.out.println(我是雅典娜女神,我死了!);}}}}运行结果如图5-3所示。图5-3运行结果三、案例总结1、在多线程程序中,一旦前台线程(例如主线程)结束,后台线程也就结束了。2、要将某个线程设置为后台线程,该线程的setDaemon()方法必须在start()方法之前调用,否则会引发IllegalThreadStateException异常。案例5-4线程的优先级一、案例描述1、考核知识点编号:00105007名称:线程的优先级2、练习目标了解线程中优先级的概念和作用掌握设置线程优先级的方法掌握线程设置优先级方法中的三个静态常量3、需求分析在应用程序中,如果要对线程进行调度,最直接的方式就是设置线程的优先级。这时,可以通过线程的setPriority()方法来设置线程优先级别,实现对线程的调度功能。为了让初学者掌握线程的优先级,在案例中创建3个线程,分别为它们设置不同的优先级来演示不同优先级线程的调度。4、设计思路(实现原理)1)自定义一个类Demo,使其实现Runnable接口。博学谷——让IT教学更简单,让IT学习更有效62)在Demo类中重写run()方法,在方法内编写一个for循环,循环体内打印:线程名称+循环次数。3)编写测试类Example04,在Example04类的main()方法中,创建一个Demo对象,利用Thread的构造方法创建三个线程对象并命名,使用setPriority()方法将其中两个线程的优先级设为最大和最小,最后开启三个线程的start()方法。二、案例实现classDemoimplementsRunnable{publicvoidrun(){for(intx=0;x5;x++){System.out.println(Thread.currentThread().getName()+---+x);}}}publicclassExample04{publicstaticvoidmain(String[]args){Demod=newDemo();Threadt1=newThread(d,杨过);Threadt2=newThread(d,岳不群);Threadt3=newThread(d,金龙);//设置线程的优先级t3.setPriority(Thread.MAX_PRIORITY);t2.setPriority(1);t1.start();t2.start();t3.start();}}运行结果如图5-4所示。图5-4运行结果博学谷——让IT教学更简单,让IT学习更有效7三、案例总结1、在多线程程序中,可以通过设置线程的优先级别来控制线程获得CPU执行的几率。2、线程的优先级用1~10之间的整数来表示,数字越大优先级越高。也可以使用静态常量表示线程的优先级,如:MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY。3、虽然Java中提供了10个线程优先级,但是这些优先级需要操作系统的支持,不同的操作系统对优先级的支持是不一样的,不能很好的和Java中线程优先级一一对应,因此,在设计多线程应用程序时,其功能的实现一定不能依赖于线程的优先级,而只能把线程优先级作为一种提高程序效率的手段。案例5-5线程休眠一、案例描述1、考核知识点编号:00105008名称:线程休眠2、练习目标了解线程休眠的概念和作用掌握如何使用sleep(longmillis)方法使线程休眠3、需求分析如果希望人为地控制线程,使正在执行的线程暂停,将CPU让给别的线程。这时,可以使用静态方法sleep(longmillis),该方法可以让当前正在执行的线程暂停一段时间,进入休眠等待状态。为了让初学者更好地掌握线程休眠,案例中将启动三个线程共同出售10张票来演示线程休眠及休眠引发的结果。4、设计思路(实现原理)1)自定义一个类Ticket,使其实现Runnable接口,并在该类中创建int类型私有属性tickets,赋初值为10。2)在Ticket类中重写run()方法,在方法内编写一个while循环。循环体内判断ticket值,当大于0时,使用sleep(longmillis)方法使线程休眠1秒钟,并打印:当前线程名称+“正在出售第”+循环次数;否则结束循环。每执行一次while循环,tickets值减一。3)编写测试类Example05,在Example05类的main()方法中,创建一个Ticket对象,利用Thread的