第8章多线程本章重点�线程的创建�线程的基本控制方法�线程的互斥与同步更多优质自考资料尽在百度贴吧自考乐园俱乐部()欢迎 加入...欢迎 交流...止不住的惊喜等着你.........2线程概念1.1.1.1.什么是线程:线程就是程序中单独顺序的流控制。线程本身不能运行,它只能用于程序中。3线程概念2.什么是多线程:多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务.4线程的生命周期线程的生命周期:一个线程从创建到死亡的过程。线程的生命周期可分为五个状态:1.创建状态2.就绪状态3.运行状态4.阻塞状态5.死亡状态5线程的生命周期线程的状态转换图:6线程的生命周期1.1.1.1.创建状态�当用new操作符创建一个新的线程对象时,该线程处于创建状态。�处于创建状态的线程只是一个空的线程对象,系统不为它分配资源�此时只能调用start方法启动该线程,调用其它任何方法都会产生线程非法状态异常。7线程的生命周期2.就绪状态�执行线程的start()方法将为线程分配必须的系统资源,安排其运行,并调用线程体—run()方法,这样就使得该线程处于可运行(Runnable)状态。�这一状态并不是运行中状态(Running),因为线程也许实际上并未真正运行。8线程的生命周期3.运行状态�是某个就绪状态的线程获得CPU资源,正在运行,�如果有更高优先级的线程进入就绪状态,则该线程就被迫放弃对CPU的控制进入就绪状态,可使用yield()方法主动放弃CPU,也可能由于执行结束或执行stop()方法进入死亡状态.9线程的生命周期3.阻塞状态当发生下列事件时,处于运行状态的线程会转入到阻塞状态。�调用了sleep()方法;�线程调用wait方法所等待的特定条件的满足�线程输入/输出阻塞10线程的生命周期从阻塞状态恢复到就绪状态三种途径:�处于睡眠状态的线程在指定的时间过去后�如果线程在等待某一条件,另一个对象必须通过notify()或notifyAll()方法通知等待进程条件的改变�如果线程是因为输入/输出阻塞,输入/输出完成11线程的生命周期4.4.4.4.死亡状态当线程的run方法执行结束后,该线程自然死亡。12线程的实现在Java中通过run方法为线程指明要完成的任务,有两种技术来为线程提供run方法。1.继承Thread类并重载run方法。2.通过定义实现Runnable接口的类进而实现run方法。13线程的实现1.继承Thread类并重载run方法。�Thread类:是专门用来创建线程和对线程进行操作的类。Thread中定义了许多方法对线程进行操作。�Thread类在缺省情况下run方法是空的。可以通过继承Thread类并重写Thread类的run方法实现用户线程。14线程的实现1.继承Thread类并重载run方法。总体结构如下:publicclassMyThreadextendsThread{publicvoidrun(){……}}MyThreadt=newMyThread();t.start();15线程的实现2.执行Runnable接口的类实现run方法。通过建立一个实现了Runnable接口的对象,并以它作为线程的目标对象来创建一个线程。Runnable接口:定义了一个抽象方法run()。定义如下:publicinterfacejava.lang.Runnable{publicabstractvoidrun();}16线程的实现2.执行Runnable接口的类实现run方法。创建的总体框架如下:•classMyRunnerimplementsRunnable{publicvoidrun(){…………}}•MyRunnerr=newMyRunner();•Threadt=newThread(ThreadGroupgroup,Runnabletarget,Stringname);例如:Threadt=newThread(r,“aa”);17线程的实现总结:1.两种方法均需执行线程的start方法为线程分配必须的系统资源、调度线程运行并执行线程的run方法。2.在具体应用中,采用哪种方法来构造线程体要视情况而定。通常,当一个线程已继承了另一个类时,就应该用第二种方法来构造,即实现Runnable接口。3.线程的消亡不能通过调用一个stop()命令。而是让run()方法自然结束。18线程的优先级1.1.1.1.线程的优先级及其设置设置优先级是为了在多线程环境中便于系统对线程的调度,优先级高的线程将优先执行一个线程的优先级设置遵从以下原则:�线程创建时,子进程继承父进程的优先级�线程创建后,可通过调用setPriority()方法改变优先级。�线程的优先级是1-10之间的正整数。1-MIN_PRIORITY,10–MAX_PRIORITY5-NORM_PRIORITY19线程的优先级2.2.2.2.线程的调度策略线程调度器选择优先级最高的线程运行。但是,如果发生以下情况,就会终止线程的运行�线程体中调用了yield()方法,让出了对CPU的占用权�线程体中调用了sleep()方法,使线程进入睡眠状态�线程由于I/O操作而受阻塞�另一个更高优先级的线程出现。�在支持时间片的系统中,该线程的时间片用完。20多线程的同步1.1.1.1.为什么要引入同步机制在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源。必须对这种潜在资源冲突进行预防。解决方法:在线程使用一个资源时为其加锁即可。访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁。21多线程的同步2.2.2.2.怎样实现同步对于访问某个关键共享资源的所有方法,都必须把它们设为synchronized例如:synchronizedvoidf(){/*...*/}synchronizedvoidg(){/*...*/}如果想保护某些资源不被多个线程同时访问,可以强制通过synchronized方法访问那些资源。调用synchronized方法时,对象就会被锁定。22多线程的同步publicclassMyStack{intidx=0;char[]data=newchar[6];publicsynchronizedvoidpush(charc){data[idx]=c;idx++;}publicsynchronizedcharpop(){idx--;returndata[idx];}23多线程的同步2.2.2.2.怎样实现同步说明:•当synchronized方法执行完或发生异常时,会自动释放锁。•被synchronized保护的数据应该是私有(private)的。24多线程的同步2.2.2.2.怎样实现同步同步的线程状态图:25多线程的同步2.2.2.2.怎样实现同步线程间的相互作用:•waitandnotify•Thepools:–Waitpool–Lockpool26多线程的同步2.2.2.2.怎样实现同步具有wait()和notify()的线程状态图:27线程组1.1.1.1.线程组:所有线程都隶属于一个线程组。那可以是一个默认线程组,亦可是一个创建线程时明确指定的组。说明:–在创建之初,线程被限制到一个组里,而且不能改变到一个不同的组。–若创建多个线程而不指定一个组,它们就会与创建它的线程属于同一个组。28线程组例子:publicThread(ThreadGroupgroup,Runnabletarget)publicThread(ThreadGroupgroup,Stringname)publicThread(ThreadGroupgroup,Runnabletarget,Stringname)ThreadGroupmyThreadGroup=newThreadGroup(MyGroupofThreads);ThreadmyThread=newThread(myThreadGroup,athreadformygroup);theGroup=myThread.getThreadGroup();