线程状态分类
新建与被终止还是很容易理解的,可运行就是线程的正常情况。锁阻塞是指为防止出现线程安全问题而使用同步技术产生的状态。之后详细介绍以下计时等待与无限等待状态
等待唤醒机制
- 一个线程进行了规定操作后,就进入等待状态
wait()
, 等待其他线程执行完他们的指定代码过后 再将
其唤醒notify()
;在有多个线程进行等待时, 如果需要,可以使用notifyAll()
来唤醒所有的等待线程。
wait/notify
就是线程间的一种协作机制。
Timed Waiting (计时等待)
- 当我们调用了sleep方法之后,当前执行的线程就进入到“休眠状态”,其实就是所谓的Timed Waiting(计时等待)
注意:- 进入
TIMED_WAITING
状态的一种常见情形是调用的sleep
方法,单独的线程也可以调用,不一定非要有协作关系。 - 为了让其他线程有机会执行,可以将
Thread.sleep()
的调用放线程run()
之内。这样才能保证该线程执行过程中会睡眠 - sleep与锁无关,线程睡眠到期自动苏醒,并返回到
Runnable
(可运行)状态。 - sleep()中指定的时间是线程不会运行的最短时间。因此,
sleep()
方法不能保证该线程睡眠到期后就开始立刻执行。
- 进入
例:
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
if(i%10 == 0){
System.out.println();
System.out.println("======================" + i);
}
System.out.print(i + " ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new MyThread().start();
}
Waiting (无限等待)
使用方法:
等待唤醒:Object.wait
线程不再活动,不再参与调度,进入 wait set
中
释放:Object.notify()
方法 选取所通知对象的 wait set
中的一个线程释放
Object.notifyAll()
方法。 · 则释放所通知对象的 wait set
上的全部线程。
注意:
wait
方法与notify
方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify
唤醒使用同一个锁对
象调用的wait方法后的线程。wait
方法与notify
方法是属于Objec
t类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继
承了Object类的。wait
方法与notify
方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方
法。
public class WaitingTest {
public static Object obj = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj) {
try {
System.out.println(Thread.currentThread().getName() +
"获取锁对象,调用wait方法,进去waiting状态");
obj.wait();
} catch (InterruptedException e) {
e.getStackTrace();
}
System.out.println(Thread.currentThread().getName() + "从waiting状态中醒来,获取锁对象,继续执行");
System.out.println();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() +
"等待5秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
obj.notify();
System.out.println(Thread.currentThread().getName() +"获取锁对象,调用notify方法,释放锁对象");
}
}
}
}).start();
}
}