您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 招标投标 > 第9章Java多线程机制
第9章Java多线程机制经常在编程遇到一个类似下列程序段的问题:classA{publicstaticvoidmain(Stringargs[]){while(true){我听朋友说话;}while(true){我向朋友说话;}}}可以将上面两个while放到两个线程中去独立执行如:线程一:while(true){我听朋友说话;}线程二:while(true){我向朋友说话;}想像一下,线程一和线程二不会互相等待,可以独立执行,互不干扰。这就是多线程编程。在Java中多线程编程要比VisualC++的简单。在Java中,使用JVM(Java虚拟机:JavaVirtualMachine),来负责调度这些线程,使得每个线程都有平等的机会获得CPU进行独立运行,并且,各个线程之间可以有联系,也可以没有联系,可以进行数据共享,也可以进行通信。9.1Java中的多线程9.1.1程序、进程与线程程序(Program):以数据、代码形式存放在磁盘上,它是死的,如果用户不去运行它,那么它就一直呆在那不动。进程(Process):如果开始运行一个程序,那么操作系统所做的工作有:在内存开辟一个不大的空间,并根据该程序的信息,组装成一个PCB(ProcessControlBlock,进程控制块),里面有该进程的重要信息,并同时,将程序的代码和数据(可能是全部的,也可能是一部分)装入内存,然后,将该程序以进程的插入到操作系统的一个就绪队列中去,这样,这个程序就可以有机会获得CPU开始运行,那么此时,程序就成为了进程。进程是活动的,有生命的,而程序是死的。线程(Thread):通常一个程序就形成一个进程,可是进程可能会太庞大了,且如果以进程为单位进行调度运行的话,进程内部又没有办法同时多段代码同时运行,如上面的例子,需要将进程进一步变小,形成多个相对独立的单位——线程。一个进程中,可以包含一个或多个线程,但至少有一个线程——主线程,就是main函数所在的那个线程,其它的线程都是由主线程直接或间接产生的。这样,一个进程中如果包含了两个线程,那么,在这个进程中,两个线程就可以像上面例子中一样,可相对独立地运行:进程一:主线程://.....线程一:while(true){我听朋友说话;}线程二:while(true){我向朋友说话;}实际上,由于一台计算机通常只有一个CPU,那么同一个时刻只有一个线程在运行,但是由于计算机运行速度非常地快,可以在10毫秒内运行许多的代码,那么,可以是这样:线程一运行了3毫秒,线程二运行了4毫秒,线程三运行了3毫秒,那么,在10毫秒内,三个线程都得到了运行,我们从外部来看,好像是这三个线程在同时运行。这三个线程之间的切换由JVM完成。9.1.2线程的状态与生命周期线程状态通常有五种基本状态,也就对应着其五个生命周期:1、创建态:当一个线程类被new出来后,这个线程就处于创建态;2、就绪(Ready)态:当线程对象通过start方法调用后,线程就被插入到就绪队列中,处于就绪状态,此时该线程可能还没有开始运行(可能此时有别的线程正在CPU上执行,JVM还没有调试到该线程,那么该线程可能会在就绪队列中呆一段时间,这段时间的长短不确定)。3、运行(Running)态:处于就绪态的线程,万事俱备,只欠CPU,如果JVM在时机成熟时,调度到该线程,那么就会把CPU给该线程,此时,该线程就处于运行态,开始运行。处于运行态的线程,可能由于某种原因(有更重要的线程要运行、自己调用Sleep方法睡觉等),又会重新回到就绪态。就绪态运行态等待态创建消亡JVM调度调用SleepI/O操作I/O完成4、等待态(Wait):处于运行态的线程,如果进行了IO输入输出调用,如调用了println输出,则JVM会暂停该线程的运行,因为输入输出与CPU无关,且时间要很长。此时JVM会剥夺该线程的CPU,从而该线程会进入到等待态。一旦输入输出完成,则该线程又会进入到就绪态,可以有机会得到CPU再次运行。5、消亡:当该线程运行完成后(通常是在run方法中通过return返回,或者通过exit方法的调用),那么该线程就处于消亡。9.1.3线程的调试与优先级在就绪态时,线程是在一个就绪队列中(队列可以理解为队伍,可能老长),每个线程是排在队伍的末尾,就是说,可能很多的线程正在就绪队列中,JVM总是从前往后进行调度。所以可以定义线程的优先级,JVM会根据优先级的高低进行优先调度。Java通常定义了10个级别的优先级:Thread.MIN_PRIORITY(值为1)~Thread.NORM_PRIORITY(值为5)~Thread.MAX_PRIORITY(值为10),值越大,优先级越高(注意,有些操作系统相反,当然在Java中不用管不同的操作系统的区别)可以调用Thread.setPriority方法来设定优先级,通常值就是1~10,如果如果定义优先级,那么默认取5需要说明的是,即使你把你的线程的优先级定为10(最高),也不能保证一定会先调用你的线程。所以你的编程中,不应该依赖于优先级来保障你的线程一定先运行。所以,编程中,尽量不要使用优先级。在Java中进行多线程编程,主要有三种方法:方法一:创建一个从Thread继承下来的子类,一定要实现其run方法;方法二:创建匿名的Thread类,其中实现了run方法方法三:创建实现Runnable接口的类,然后使用该类来new一个Thread对象。9.2Thread类的子类创建线程一般方法:classMyThredextendsThread{publicvoidrun(){//....}}在需要的地方,用该类来new一个对象,并调用其start方法来启动该线程:publicstaticvoidmain(Stringargs[]){MyThreadt;t=newMyThread();t.start();//启动线程}如:publicclassJ_6_7{publicstaticvoidmain(String[]args){MyThread1t1;MyThread2t2;t1=newMyThread1();//构建线程类一对象t2=newMyThread2();//构建线程类二对象t1.start();//启动线程一t2.start();//启动线程二for(inti=1;i=10;i++){//主线程循环System.out.println(主线程);try{Thread.sleep(50);//主线程睡眠50毫秒}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}classMyThread1extendsThread{publicvoidrun(){inti;for(i=1;i=10;i++){System.out.println(这是线程一);try{Thread.sleep(50);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}classMyThread2extendsThread{publicvoidrun(){inti;for(i=1;i=10;i++){System.out.println(线程二运行中……);try{Thread.sleep(50);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}运行的结果可能如下:主线程线程二运行中……这是线程一主线程这是线程一线程二运行中……主线程这是线程一线程二运行中……主线程线程二运行中……这是线程一这是线程一主线程线程二运行中……这是线程一主线程线程二运行中……主线程线程二运行中……这是线程一主线程线程二运行中……这是线程一主线程线程二运行中……这是线程一这是线程一线程二运行中……主线程在启动线程时,通过调用该类的start方法,就是运行其run方法。所以线程类中,唯一对外可见的方法就是run方法,其它的方法都是为它服务。9.3使用匿名Thread类的方法创建线程在Java中,可以使用匿名的方式来创建类,Thread类也可以,但一定要实现run方法,并且要在匿名类后加上.start来启动它,否则的话,无法启动,如:newThread(){publicvoidrun(){inti;for(i=1;i=10;i++){System.out.println(这是线程三);try{Thread.sleep(50);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}};}.start();运行可能的效果如下:这是线程三主线程这是线程三主线程这是线程三主线程主线程这是线程三主线程这是线程三主线程这是线程三这是线程三主线程主线程这是线程三主线程这是线程三主线程这是线程三9.4使用Runnable接口的方法创建线程其过程如下:(1)写一个类,实现Runnable的接口,其中至少需要实现其run方法,如:classMyRunnableThreadimplementsRunnable{//类的其它的方法、属性publicvoidrun(){//run方法体}}(2)在需要的地方定义一个Thread类型的变量:Threadt;(3)new出MyThread类对象MyRunnableThreadmrt=newMyRunnableThread();(4)在需要的地方,new出一个Thread对象,但是,要用到上面的MyThread类对象mrt:t=newThread(mrt);(5)调用t的start方法,启动线程:t.start();如下例:classMyRunnableThreadimplementsRunnable{//别的属性和方法publicvoidrun(){inti;for(i=1;i=10;i++){System.out.println(这是线程四);try{Thread.sleep(50);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}publicclassJ_6_7{publicstaticvoidmain(String[]args){/*创建方法三:使用Runnable接口*/Threadt;MyRunnableThreadmrt=newMyRunnableThread();t=newThread(mrt);t.start();for(inti=1;i=10;i++){System.out.println(主线程);try{Thread.sleep(50);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}可能的运行效果:主线程这是线程四主线程这是线程四这是线程四主线程这是线程四主线程主线程这是线程四这是线程四主线程这是线程四主线程这是线程四主线程这是线程四主线程主线程这是线程四9.5线程的常用的方法字段摘要staticintMAX_PRIORITY线程可以具有的最高优先级。staticintMIN_PRIORITY线程可以具有的最低优先级。staticintNORM_PRIORITY分配给线程的默认优先级。构造方法摘要Thread()分配新的Thread对象。Thread(Runnabletarget)分配新的Thread对象。Thread(Runnabletarget,Stringname)分配新的Thread对象。Thread(Stringn
本文标题:第9章Java多线程机制
链接地址:https://www.777doc.com/doc-2199705 .html