Java多线程 - 线程的生命周期

    技术2022-07-10  122

    Java多线程 - 线程的生命周期

    引言: Java线程被创建之后,并非是一启动就开始执行,也不是一直处于执行状态。 在线程的生命周期中,需要经过新建、就绪、运行、阻塞和死亡五种状态。 线程启动后,不可能一直占用着CPU独自运行,CPU需要再多条线程之间切换,于是线程状态也会多次在运行和就绪之间切换。

    一、新建和就绪状态

    当程序使用new关键字创建了一个线程之后,这个线程就会一直处于新建状态,此时它和Java对象一样,仅仅由Java虚拟机为其分配内存,并且初始化其成员变量的值,此时线程对象没有任何线程的动态特征,程序也不会执行线程的线程执行体。 当线程对象调用了start()方法之后,该线程就会处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器。处于这个状态的线程并没有开始运行,只是表示该线程可以运行了,至于该线程何时开始运行,这个取决于JVM里线程调度器的调度

    注意:启动线程需要使用的是start()方法,而不是run()方法,永远不许调用线程对象的run()方法! 原因: 调用start()方法,来启动线程,会把该run()方法当成线程执行体来处理,但是如果说你要是直接调用了线程对象的run()方法,则run()方法立即就会别自行,而且,在run()方法之前的其他线程无法并发执行。也就是说:如果直接调用线程对象的run()方法,系统会把线程对象当做一个普通对象来进行处理,且run()方法也只是一个普通的方法了,并非是一个线程执行体。

    class demo { public static void main(String[] args) { MyThread thread1 = new MyThread(); thread1.run(); MyThread thread2 = new MyThread(); thread2.start(); } } class MyThread extends Thread{ @Override public void run(){ System.out.println(Thread.currentThread().getName()); } } /* 运行结果: main Thread-1 由此可知,如果调用run方法,则知识当成一个普通的方法运行,其线程是main线程 */

    注意:只能对处于新建状态的线程调用start()方法,否则将会引起异常IllegalThreadStateException

    小知识: 如果你想让你创建的进程立刻开始运行,你可以使用Thread.sleep(1)来让当前运行的线程(主线程)睡眠1ms,1ms足够了,因为在这1ms内CPU并不会空闲,它回去执行另一个处于就绪状态的线程,这样子线程就开始立即执行。

    二、运行和阻塞状态

    如果处于就绪状态的线程获得了CPU, 开始执行run()方法的线程执行体,则该线程处于运行状态,如果说,计算机只有一个CPU,那么在任何时刻只有一个线程处于运行状态,当然,如果是一个多处理器的机器上,将会有多个线程并行,(注意:并行:同一时刻,有多条指令在多个处理器上同时执行。)当然,当线程数大于处理器数时,依然会有多个线程在同一CPU上轮换的现象。

    当一个线程开始运行之后,不存在一直处于运行状态(当然,如果说线程执行体太短,瞬间完成, 那当我没说),线程在运行的过程中需要被中断,目的是为了使得别的线程获得一个执行的机会,线程调度的具体细节取决于底层平台所采用的的侧率。

    目前,现代桌面和服务器操作系统均采用抢占式调度策略,但是有一些小型设备如同手机,可能采用协作式调度策略。

    线程进入阻塞状态的可能原因:

    线程调用sleep()方法主动放弃所占用的处理器资源线程调用了一个阻塞式IO方法,在该方法返回之前,该线程会一直被阻塞线程试图获得一个同步监视器,但是该同步监视器别的线程所拥有着线程在等待某个通知程序调用了线程的suspend()方法将该线程挂起(注意:该方法容易导致死锁)

    当线程正在被执行的时候阻塞了,其他的线程就可以获得执行的机会,被阻塞的线程会在何时的时候重新进入就绪状态。 针对上面导致线程进入阻塞状态的可能原因,可以分析出,发生以下情况,则会解除上面的阻塞:

    调用sleep()方法的线程已经过了指定时间了线程调用的阻塞式IO方法已经返回线程成功地获得试图取得的同步监视器线程正在等待某个通知时,其他线程发出了一个通知处于挂起状态的线程调用了resume()修复方法

    三、线程死亡

    线程也会执行结束,当它执行结束的之后,就会处于死亡状态。 线程会以如下的方式结束:

    run()或call()方法执行完成,线程正常结束线程跑出一个未捕获的Exception或者Error直接调用该线程的stop()方法来结束该线程 – 该方法容易导致死锁,不推荐使用

    注意:

    当主线程结束的时候,其他的线程不会受到任何影响,且不会随之结束,一旦子线程启动起来之后,他就会有与主线程一样的地位,不会受到主线程的影响不要试图对一个已经死亡的线程调用start()方法使它重新启动,死亡就是死亡了,就像恋爱被甩了,你还打算舔狗复合?!该线程已经不可以再次作为线程执行。不仅不要对死亡状态的线程调用start()方法,且程序只能够对新建的线程调用start()方法,当然,对新建状态的线程调用两次start()方法也是错误的,会引发IllegalThreadState异常。判断线程死亡:可以调用线程对象的isAlive()方法,当线程处于就绪,运行,阻塞三种状态的时候,返回true,如果处于新建和死亡两种状态,该方法就会返回false
    Processed: 0.010, SQL: 9