线程状态的转换
一、线程状态
新状态:创建线程对象。未执行start()方法。
就绪:已经执行start()方法,具有运行资格,但是并不是马上运行,何时运行需要系统的调度。
运行:线程获得CPU资源,处于运行状态。
阻塞:线程有资格运行,但是他的运行需要条件,当条件触发时,可以装换为运行状态。
死亡:run()执行完,可以认为死去。线程死亡后,不能再次复活。
二、阻止正在执行的线程
- join()
对于join()可能会让很多人困惑,比如说对于t.join()到底是怎么样运行的。对于线程t到底会有什么样的影响。
先看Jdk对join()的介绍:
public final void join(long millis)
throws InterruptedException
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
查看源码:
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;
}
}
}
从源码可以看出join方法基于wait方法实现。
wait()是Object的方法
查看Jdk对wait方法的介绍:
public final void wait()
throws InterruptedException
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
wait方法让当前线程等待。由此可以看出t.join()是让当前执行这个方法的线程等待,如果是在main方法中,则main线程需要等待t线程执行完,才能执行。可以执行join方法是将当前线程加到t线程的尾部。
例子:
public class MyThread extends Thread{
@Override
public void run(){
for (int i = 0;i < 5;i++) {
System.out.println(Thread.currentThread().getName() + "-" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
对于测试程序:
public class Test {
public static void main(String[] args) {
MyThread myThreadA = new MyThread();
MyThread myThreadB = new MyThread();
myThreadA.setName("A");
myThreadB.setName("B");
myThreadA.start();
//myThreadB.start();
try {
myThreadA.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main over");
}
}
执行结果为:
A-0
A-1
A-2
A-3
A-4
main over
可以看出main在myThreadA执行完之后才继续执行。
2. Thread.sleep()
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。
3. yield()
查看JDK介绍:
A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.
即yield的作用是释放当前线程所占用的资源,即让当前正在执行的程序从运行状态转为可执行状态。而当前CPU的资源由JVM自动调度给其他线程。
JVM调度的机制是基于优先级的抢占调度机制,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。
yield的暂停时间并不确定,可能会立即再次拥有CPU资源继续执行。
JVM调度的机制是基于优先级的抢占调度机制,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。
但这仅仅是大多数情况。yield的暂停时间并不确定,可能会立即再次拥有CPU资源继续执行。