Object和Thread类中, 为我们提供了操作线程的一些方法, 可以让我们对运行中的线程进行控制
一、按归属分类
类别 | 方法 | 简介 |
Object | wait()/wait(long timeout)/wait(long timeout, int nanos) | 让当前线程进入等待状态,并释放所持锁 |
notify()/notifyAll() | 唤醒当前对象上的等待线程 | |
Thread | start() | 启动线程 |
currentThread() | 返回当前运行的线程的引用 | |
getId() | 取得线程的唯一标识 | |
isAlive() | 判断当前线程是否处于活动状态 | |
getName()/setName() | 用来得到或者设置线程名称 | |
getPriority()和setPriority() | 用来获取和设置线程优先级。 | |
setDaemon()和isDaemon() | 用来设置线程是否成为守护线程和判断线程是否是守护线程。 | |
sleep(long millis)/sleep(long millis, int nanos) | sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务 | |
yield() | 类似于sleep,但不会等待,而是直接回到就绪状态 | |
join()/join(long millis)/join(long millis, int nanos) | 当前线程调用A.join(), 把当前线程加入到A线程后, 顺序执行 | |
interrupt() | 停止线程 |
二、方法详解
1.wait()/notify()
wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)
wait(long timeout)让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的notify()方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
2.sleep()
方法sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象
3.yield()
调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。
注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。
4.join()
方法join()的作用是等待线程对象销毁。
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。
比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
5.interrupt()/interrupted()/isInterrupted()
interrupt() 中断线程
在Thread.java类里提供了两种方法判断线程是否为停止的。
this.interrupted():测试当前线程是否已经中断(静态方法)。如果连续调用该方法,则第二次调用将返回false。在api文档中说明interrupted()方法具有清除状态的功能。执行后具有将状态标识清除为false的功能。
this.isInterrupted():测试线程是否已经中断,但是不能清除状态标识。
示例:
public class MyThread4 extends Thread {
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 50000; i++) {
if (this.isInterrupted()) {
System.out.println( "线程已经结束,我要退出" );
// return;
throw new InterruptedException();
}
System.out.println( "i=" + (i + 1) );
}
System.out.println( "我是for下面的语句,我被执行说明线程没有真正结束" );
} catch (InterruptedException e) {
System.out.println( "进入MyThread.java类中run方法的catch异常了" );
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
MyThread4 myThread4 = new MyThread4();
myThread4.start();
Thread.sleep( 20);
myThread4.interrupt();
} catch (InterruptedException e) {
System.out.println( "main catch" );
e.printStackTrace();
}
}
三、注意点
1. sleep(0)与 yeild()区别
sleep 的意思是告诉操作系统自己要休息 n 毫秒,这段时间就让给另一个就绪的线程吧。当 n=0 的时候,意思是要放弃自己剩下的时间片,但是仍然是就绪状态,其实意思和 Yield 有点类似。但是 Sleep(0) 只允许那些优先级相等或更高的线程使用当前的CPU,其它线程只能等着挨饿了。如果没有合适的线程,那当前线程会重新使用 CPU 时间片。
Yield 的中文翻译为 “放弃”,这里意思是主动放弃当前线程的时间片,并让操作系统调度其它就绪态的线程使用一个时间片。但是如果调用 Yield,只是把当前线程放入到就绪队列中,而不是阻塞队列。如果没有找到其它就绪态的线程,则当前线程继续运行。当某个线程调用了yield()方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行机会。
2.Object的wait()和notify()
- 都需要拥有Object对象锁才能调用
- 可以使用此机制进行多线程之间的协同、通信,实现多线程的可见性