在Java并发编程中,线程所处的状态以及创建线程的方式算是’开学第一课’了。而从本文开始,我将对Java并发做一个系统的认识。话不多说,开始进入主题。
一:线程状态
在Thread类中详细的枚举了线程的状态,如下:
public enum State {
/**
* 创建了线程还未调用srart()方法的时候,线程处于NEW的状态
*/
NEW,
/**
* 线程处于可运行的状态,在此状态下,如果操作系统分配了相应的时间片
* 则线程将开始真正的运行
*/
RUNNABLE,
/**
* 线程处于阻塞状态,在此状态下将等待着直到获得监视器锁。
* 以下情况将进入阻塞状态
* 一:进入同步被synchronized修饰的同步代码块,方法或者锁的重入
*/
BLOCKED,
/**
* 线程出于等待的状态,以下的方法将会使线程出于此状态:
* 一:调用了object.wait()方法
* 二:调用了thread.join()方法
* 三:调用了LockSupport()方法
* 处于于此状态的线程将等待着另一个线程执行特定的操作,比如调用了wait()方法
* 将等待着另一个线程调用notify()或者notifyAll 的方法唤醒。
*/
WAITING,
/**
* 超时等待的状态.以下操作将进入超时等待的状态:
* 一:Thread.sleep()方法的调用
* 二:object.wait(long) 加入超时时间的wait方法
* 三:thread.join(long millis)
* 四:LockSupport.parkNanos() 或者LockSupport..parkUntil()
*/
TIMED_WAITING,
/**
* 终止状态的线程
* 线程完成了所有的操作处于此状态
*/
TERMINATED;
}
以上的枚举我们可以清楚的看到线程有NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED 6种状态,线程总是处于6种状态的某一种。我们将通过一个图更加清楚的看看各个状态之间是怎么变更的:
上图需要说明的是,在线程的枚举状态中,其实并没有RUNING的状态,RUNNABLE与RUNNING的状态的区别是是否获得了由操作系统分配的时间片,这里为了流程更加的清晰易懂,做了区分的处理。 以下,将从代码的角度分析下线程的状态:
public class ThreadState implements Runnable{
@Override
public void run() {
//RUNNABLE
System.out.println("线程的状态为:"+Thread.currentThread().getState());
}
public static void main(String[] args) {
Thread thread =new Thread(new ThreadState());
//NEW
System.out.println("线程的状态为:"+thread.getState());
thread.start();
}
}
才创建线程,线程处于NEW状态,调用start方法后,获得时间片后,执行run方法,线程处于RUNNABLE状态。
public class ThreadState implements Runnable{
@Override
public void run() {
synchronized (ThreadState.class){
while (true){
System.out.println("线程的状态为:"+Thread.currentThread().getState());
}
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
Thread thread2 =new Thread(threadState);
thread1.start();
thread2.start();
}
}
查看线程的状态,
可以看到先获得时间片的线程处于RUNNABLE的状态,而另外一个线程则处于BLOCK的状态。
public class ThreadState implements Runnable{
@Override
public void run() {
synchronized (this){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
thread1.start();
}
}
当调用wait方法的时候,当前线程会处于WAITING状态
public class ThreadState implements Runnable{
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
thread1.start();
}
}
当调用了sleep方法的时候,则线程处于TIMED_WAITING超时等待状态。
二:创建线程的方式
这里主要是对其进行一个总结:
1:实现Runnable接口或匿名内部类的方式
2:继承Thread类
3:线程池的实现
4:带返回值的线程创建方式(Callable与FutureTask)
5:Spring对异步的支持(@Async)
6:Lamada表达式中的并行计算
更多深入解析,你可以关注我的微信公众号: 南瓜小灯