线程状态 | 意义 |
---|---|
NEW | 线程的初始状态,未被start() |
RUNNABLE | 线程被调用start后,无论还有没有进入Runnable接口的逻辑,都是runnable状态 |
BLOCKED | 线程阻塞在某个锁上,等抢到锁。你可以想象处于这种状态的线程就像在门外拍门不停想要进入的人一样 |
WAITING | 线程执行了sleep或者锁的wait后,处于一种假死状态,不会做任何事,直到被notify唤醒 |
TIMED_WAITING | 被执行了有时间的wait后的状态,醒过来后如果还是拿不到锁就会转到BLOCKED状态,拿到了就是RUNNABLE |
TERMINATED | 执行完了Runnable逻辑,GG思密达 |
NEW
@Test
public void newState() {
Thread thread = new Thread();
System.out.println(thread.getState());//NEW
}
RUNNABLE
@Test
public void runnableState() {
new Thread(() -> {
System.out.println("current thread state when doing sth : "
+ Thread.currentThread().getState());//RUNNABLE
}).start();
}
BLOCKED
@Test
public void BlockedState() throws InterruptedException {
Object lock = new Object();
//启动一个线程获取锁,然后假装很忙,再也不放手
new Thread(() -> {
synchronized (lock) {
while (true) {
}
}
}).start();
Thread threadB = new Thread(() -> {
synchronized (lock) {
System.out.println("lock acquired!");
}
});
threadB.start();//线程开始后,状态变成RUNNABLE
TimeUnit.SECONDS.sleep(5L);//让主线程在这暂停5S,此时B线程已经开始执行,尝试去获取锁,当然是获取不到的
System.out.println(threadB.getState());//BLOCKED
}
WAITING和TIMED_WAITING
先构造一个资源对象,内部有一个锁,调节线程对该资源对象的争夺
private class ValuableResource {
private Object lock = new Object();
/***
* 线程获取到锁后,锁调用自己的wait方法向当前捏着自己的线程说,放开我,你去等着
* 线程就会变成WAITING,注意这里的线程同时也会放弃锁的使用权
* @throws InterruptedException
*/
public void doSthWaiting() throws InterruptedException {
synchronized (lock) {
lock.wait();
}
}
public void doSthTimedWaiting() throws InterruptedException {
synchronized (lock) {
lock.wait(3000L);
while (true) {
}
}
}
}
WAITING
线程启动后,尝试去调用资源的doSthWaiting方法,此方法的逻辑是进来占用了锁的线程,会立即被锁告知请放开我,去门外等一等,所以这个线程最后会变成WAITING状态,注意这个wait方法是锁的方法,它的作用是告知当前占用了此锁的线程进入WAITING状态,并且放弃对此锁的占用
@Test
public void WaitedState() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
new ValuableResource().doSthWaiting();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
thread.start();
TimeUnit.SECONDS.sleep(5L);//当前线程先等一下,让我们的目标线程充分运行
System.out.println(thread.getState());//WAITING
}
TIMED_WAITING
与上一种状态不同的是TIMED_WAITING会在时间到达后重新开始动作,你可以想象成这种状态是被锁告知了,嘿,你在门外等3S,时间到了,你该干嘛接着干嘛。
@Test
public void timedWaitingState() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
new ValuableResource().doSthTimedWaiting();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
thread.start();
TimeUnit.SECONDS.sleep(2L);
System.out.println(thread.getState());//TIMED_WAITING
TimeUnit.SECONDS.sleep(2L);
System.out.println(thread.getState());//RUNNABLE
}
线程的sleep方法,会导致线程拥有的锁失去么?
线程A先获取到锁,然后睡觉
线程B尝试去获取锁,会处于BOLOCKED状态,证明了sleep并不会影响线程对锁的占用,该咋地还是咋的
其实也可以从方法的所有权去理解:
sleep()是Thread的静态方法,它管理的是当前线程,对于线程所占有的锁的情况,并不关心。
而wait()方法是锁本身的方法,告知当前占用自己的线程放弃自己,在门外等候。
@Test
public void sleepLock() {
Object lock = new Object();
Thread threadA = new Thread(() -> {
synchronized (lock) {
try {
TimeUnit.SECONDS.sleep(100000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadA.start();
System.out.println("thread a start");
Thread threadB = new Thread(() -> {
synchronized (lock) {
System.out.println("do stm");
}
});
threadB.start();
System.out.println("thread b start");
System.out.println("thread b state: "+threadB.getState()); //BLOCKED
}
join方法
join方法任然是属于线程的方法,所以他的效果是针对这个线程的。假设当调用线程A的join方法后,会将线程A的执行流程合并到当前线程中。意思就是会等线程A执行完了,当前线程才执行下去。其实看join的逻辑。
实现的方法还是wait()方法。将线程A本身作为一个锁,通过调用锁的wait()方法,使当前线程等待,直到线程A的isActive返回false,跳出循环后,当前线程继续执行
网友评论