JAVA 线程状态 ( getState )
new
系统中的线程还未创建出来,只有Thread 对象
public class TestDEMO3 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("hello");
});
System.out.println(t.getState());
//在启动之前获取线程状态,NEW
t.start();
}
}
TERMINATED
系统中线程已经执行完了,Thread 对象还在
public class TestDEMO3 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
System.out.println("hello");
});
System.out.println(t.getState());
//在启动之前获取线程状态,NEW
t.start();
Thread.sleep(2000);
System.out.println(t.getState());
// TERMINATED
}
}
RUNNABLE
就绪状态(正在CPU上运行 / 准备好随时可以去CPU运行)
public class TestDEMO3 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while(true){
//System.out.println("hello");
}
});
System.out.println(t.getState());
//在启动之前获取线程状态,NEW
t.start();
Thread.sleep(2000);
System.out.println(t.getState());
// RUNNABLE
}
}
TIMED_WAITING
指定时间登台,sleep 方法~
public class TestDEMO3 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while(true){
//System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(t.getState());
//在启动之前获取线程状态,NEW
t.start();
Thread.sleep(2000);
System.out.println(t.getState());
// TIMED_WAITING
}
}
BLOCK
阻塞
synchronized
WAITING
线程安全问题
代码在多线程环境下执行会出 bug -> 不安全
原因
- 线程之间的调度顺序是不确定的(抢占式执行)
- 多个线程修改同一个变量(可适当调整代码结构)
- 修改操作不是原子性操作(synchronized)
- 内存可见性,引起线程不安全(volatile)
- 指令重序性,引起线程不安全(synchronized / volatile)
解决方案
synchronized
//修饰普通方法
public synchronized void doSomething(){
//...
}
//修饰代码块
public void doSomething(){
synchronized (this) {
//...
}
}
volatile
保证内存可见性,被volatile 修饰的变量,此时编译器会禁止上述优化,能够保证每次都是从内存上重新读取数据
如果没使用 volatile 修饰 flag 则程序经过编译器优化不会打印并结束
反之则正常运行
class Sign{
public volatile boolean flag = false;
}
public class TestDemo4{
public static void main(String[] args) {
Sign sign = new Sign();
Thread t1 = new Thread(()->{
while(!sign.flag){
}
System.out.println("执行完毕");
});
Thread t2 = new Thread(()->{
sign.flag = true;
});
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
t2.start();
}
}