JAVA中线程的各种状态
这张图清晰的描述了线程状态由new到dead的过程中的转换细节。
new
线程的创建一般有俩种方式
- 继承Thread
继承需要重写run方法
class TestThread extends Thread{
private static int i= 0;
public TestThread (){
i++;
}
@Override
public void run() {
System.out.println("创建的第"+i+"个线程");
}
}
- 实现Runnable接口
需要重写run方法
public class Test {
public static void main(String[] args) {
System.out.println("主线程ID:"+Thread.currentThread().getId());
TestThread test= new TestThread ();
Thread thread = new Thread(test);
thread.start();
}
}
class TestThread implements Runnable{
public TestThread () {
}
@Override
public void run() {
System.out.println("子线程ID:"+Thread.currentThread().getId());
}
}
runnable
不管是如何创建线程,都需要调用start()启动线程,由上图可知,线程是通过start方法进入runnable(可运行状态)
注意:如果直接调用run方法并不会启动线程,TestThread.run()跟调用普通方法效果一样,只有start才会创建新的线程。
running
线程进入runnable状态,获取cpu时间/资源执行程序代码,这个状态就处于running运行中。
处于运行中的线程可以主动暂停运行,再次进入runnable状态,直到下次再次获取cpu时间,进入运行状态中,这个过程叫线程阻塞。
线程阻塞的几种方式
Thread.yield();
线程让步,即释放cpu的资源时间,让给优先级更高的线程,但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
Thread.wait();
线程等待,让当前线程进入等待列队(waitting queue),同时也会让当前线程释放它所持有的锁,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法后当前线程被唤醒
Thread.sleep();
线程等待,让出cpu资源指定时间,但是不会释放持有的锁,时间过之后又会处于运行中。
Thread.join();
等待调用此方法的线程(calling thread),直到该线程完成,此线程再继续
注意:
其中Thread.wait()属于等待阻塞
线程在获取同步锁时,如果该锁被其他线程占用,则进入锁池(lock pool)中,这种情况属于同步阻塞
Thread.sleep()和Thread.join()属于主动发起的阻塞。
terminated
运行完成终止状态,线程死亡,不可恢复。