线程的几种状态
在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,
但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。
sleep,suspend,wait等方法都可以导致线程阻塞。第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。
对于已经死亡的线程,无法再使用start方法令其进入就绪。
操作线程的基本函数
wait()
当一个线程执行到wait()时, 他会进入到一个和该对象相关的等待池中,同时失去了对象的锁机制,使得其他线程可以访问.
用户可以使用notify或notifyAll来唤醒当前等待池中的线程
Note:wait()和notify(),notifyAll()必须放在Synchronized Block中,否则会抛出异常
notify()会随机唤醒一个,一般使用notifyAll()就可以
/**
* Created by yangtianrui on 17-1-1.
* 线程的wait, sleep, join, yield方法
*/
public class WaitAndNotifyDemo {
// 用于等待唤醒的对象
private final static Object sLockObject = new Object();
public static void main(String[] args) {
waitAndNotifyAll();
}
private static void waitAndNotifyAll() {
System.out.println("主线程执行");
Thread thread = new WaitThread();
thread.start();
long startTime = System.currentTimeMillis();
try {
synchronized (sLockObject) {
System.out.println("主线程等待");
sLockObject.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long deltaTime = System.currentTimeMillis();
System.out.println("主线程等待了 " + (deltaTime - startTime));
}
private static class WaitThread extends Thread {
@Override
public void run() {
try {
synchronized (sLockObject) {
Thread.sleep(3000);
// 释放当前锁
// 或者使用notifyAll();
sLockObject.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/*
主线程执行
主线程等待
主线程等待了 3000
*/
sleep()
该函数是sleep的静态函数,作用是使调用线程进入睡眠状态,因此他不能改变对象的锁机制,所以当一个Synchronized块中调用sleep(),
并不会使使当前线程释放掉这个锁,即使睡眠也持有这个对象锁
join()
等待目标线程执行完成后再继续执行
/**
* Created by yangtianrui on 17-1-1.
* Join() 阻塞当前调用Join()函数所在的线程,直到接收线程执行完毕后在执行
*/
public class JoinDemo {
public static void main(String[] args) {
Thread thread1 = new WorkerThread("worker-1");
Thread thread2 = new WorkerThread("worker-2");
thread1.start();
System.out.println("启动线程1");
try {
// worker1 的join函数后,主线程会一直阻塞到thread1执行完毕
thread1.join();
System.out.println("启动线程2");
thread2.start();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程继续执行");
}
private static class WorkerThread extends Thread {
public WorkerThread(String name) {
super(name);
}
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work in " + getName());
}
}
}
/*
启动线程1
work in worker-1
启动线程2
work in worker-2
主线程继续执行
*/
yield()
线程礼让,目标线程由运行状态转换成就绪状态,也就是让出执行权限,让其他线程得以优先执行,但其他线程能否优先执行是未知的.
Note: 让出执行时间并不是让出持有的对象锁
/**
* Created by yangtianrui on 17-1-1.
* yield()使该函数所在的线程让出执行时间给其他已经就绪的线程
* <p>
* 让出执行时间并不是让出持有的对象锁
*/
public class YieldDemo {
public static void main(String[] args) {
Thread thread1 = new YieldThread("thread-1");
Thread thread2 = new YieldThread("thread-2");
thread1.start();
thread2.start();
}
private static class YieldThread extends Thread {
public YieldThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(getName() + " priority=" + getPriority() + " i=" + i);
// 每两次,执行一次yield()
if (i % 2 == 0) {
Thread.yield();
}
}
}
}
}
/*
到偶数时,会切换一次线程
thread-1 priority=5 i=0
thread-2 priority=5 i=0
thread-1 priority=5 i=1
thread-1 priority=5 i=2
thread-2 priority=5 i=1
thread-1 priority=5 i=3
thread-2 priority=5 i=2
thread-1 priority=5 i=4
thread-2 priority=5 i=3
thread-2 priority=5 i=4
thread-1 priority=5 i=5
thread-1 priority=5 i=6
thread-2 priority=5 i=5
thread-2 priority=5 i=6
thread-1 priority=5 i=7
*/
Note: yield()调用之后,其他线程并不一定会抢占到 执行时间