线程的五种状态

java多线程

Posted by zhenghao on 2019-04-18

线程的五种状态

新建

新创建一个线程对象,但是没有调用此对象的启动方法。

就绪


线程创建后,调用了start()的方法。该线程位于运行的线程池中,等待cpu调度。

运行


线程获取了cpu时间片,执行程序代码。

阻塞


线程因为某种原因放弃了对CPU的使用,暂时停止运行。

等待阻塞:运行的线程执行了wait()方法,jvm把该线程放入到等待池中。

同步阻塞:运行的线程获取同步锁的时候,若该同步锁被其余的线程占用,则jvm会把线程放入到锁池中

其他阻塞:运行的线程执行sleep或者join方法,或者I/O请求,jvm会把该线程设置为阻塞状态。

死亡


线程正常结束进入死亡状态。

![image-20190806210856459](/Users/zhenghao/Library/Application Support/typora-user-images/image-20190806210856459.png)

join


等待这个线程结束,也就是说t.join()方法阻塞调用此方法的线程进入等待阻塞状态,直到t完成,此线程在继续。

我门看一下join的源代码,也就是说当mills等于0的时候,会进入到while(isAlive())的循环,即只要子线程或者,主线程就不停等待。虽然调用的是子线程的wait()方法,但是他是通过主线程去调用的,所以休眠的是主线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;

if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

wait


暂停当前线程进入等待状态。

我门看下面这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ThreadTest implements Runnable {
int number = 10;

public void firstMethod() throws Exception {
synchronized (this) {
number += 100;
System.out.println(number);
}
}

public void secondMethod() throws Exception {
synchronized (this) {
// Thread.sleep(2000);
this.wait(2000);
number += 200;
}
}

@Override
public void run() {
try {
firstMethod();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
ThreadTest threadTest = new ThreadTest();
Thread thread = new Thread(threadTest);
thread.start();
threadTest.secondMethod();
System.out.println("number="+threadTest.number);
}

运行结果:

1.如果secondMethod()中调用的是sleep(2000)

310
number=310

2.如果secondMethod()中调用的是this.wait(2000)

110
number=310

分析:main方法的优先等级高于子线程的优先等级,所以会先调用secondMethod(),如果secondMethod()中是sleep 那么ThreadTest处于休眠状态,这时候ThreadTest线程启动调用run方法,但是这时候secondMethod()已经拿到ThreadTest的锁,并且sleep不会释放锁,那么这时候firstMethod()方法进不来,需要等待sleep结束后,这时候number会加上这个200,然后在firstMethod()中在加100,结果为310,main方法中也为310.

如果secondMethod()中是wait(),wait()方法会释放锁,这时候wait()暂停当前调用他的main线程,因为锁被释放所以firstMethod()方法直接执行,输出为110,wait结束后,main线程输出最终结果310.

sleep join wait 方法的区别


Sleep()暂停当前线程,不会释放锁。

Join() 和wait() 暂停调它用的线程,会释放锁。

join() 是object中的方法,wait()是thread中的方法。

wait()方法必须在synchronized中,否则会抛出java.lang.IllegalMonitorStateException

join() 方法可以不在synchronized中。

yield()


Yield()的作用是让步,它能够让当前线程从运行状态到就绪状态,其他线程可以获取到执行的权,也有可能是当前线程又从就绪状态到运行状态。

举个例子:一群朋友在排队上车,这时候到yield 上车的时候,他不马上上去,而是说大家一起上,谁先上去就是谁的。那么有可能是yiel的又上去了,也有可能是其余人(线程)上去了,到了运行状态。