Java 线程使用一种机制来表想要终止他。这个中断机制依靠线程对象来检查当前线程是否需要中断,同时对象也可以决定是否响应中断请求。
Java 中断线程的方法为 Thread.interrupt()
,该方法会读取中断标志位并重置中断标志位。同时我们可以使用 Thread.isInterrupted()
方法来判断线程是否收到中断信号。
在调用 interrupt
方法时,如果线程处于 WAITING
状态或者 TIMED_WAITING
状态,则会抛出一个 InterruptedException
异常。
【示例】
待中断的线程
该线程主要负责不断答应质数
public class PrimeGenerator extends Thread {
@Override
public void run() {
long number = 1L;
while (true) {
if(isPrime(number)) {
System.out.printf("Number %d is Prime\n", number);
}
if(isInterrupted()) {
System.out.println("The Prime Generator has been Interrupted\n");
break;
}
number++;
}
}
private boolean isPrime(long number) {
if(number <=2) {
return true;
}
for(long i=2; i<number; i++) {
if((number %i)==0) {
return false;
}
}
return true;
}
}
Main 方法
调用线程并中断线程
public class Main {
public static void main(String[] args) {
Thread task = new PrimeGenerator();
task.start();
try {
Thread.sleep(5000);
}catch(InterruptedException e) {
e.printStackTrace();
}
task.interrupt();
System.out.printf("Main: Status of the Thread: %s\n", task.getState());
System.out.printf("Main: IsInterrupted: %s\n", task.isInterrupted());
System.out.printf("Main: Is Alive %s\n", task.isAlive());
}
}
PS: 线程在调用
interrupt
方法时会强制唤醒线程
线程休眠有两种方式,一种是 Thread.sleep()
方法,另一种是使用 TimeUnit
枚举类的 sleep()
方法。
两种休眠方法的区别:
Thread.sleep()
:接受一个long 类型的变量,时间单位为毫秒TimeUnit
: 可以自动设定时间单位。【示例】
TimeUnit.SECONDS.sleeep(5);
线程的等待的常用函数为 Object.wait()
而线程唤醒的常用函数为 Object.notiyfy()
和 Object.notifyall()
wait()
方法会释放当前所占有的锁,让线程进入到重新请求锁的状态来实现阻塞
notify()
与 notifyAll()
会通知相应的线程去重新获得锁。
为什么线程的等待与唤醒会放在 Object 类中?
要想更好的理解这个问题可以看以下代码
synchronized(obj){
...
obj.wait();
...
}
synchronized(obj){
...
obj.notify();
...
}
当我们在执行过程中,线程已经不满足继续执行的条件导致阻塞,那么我么需要释放相应的资源,但同时我们又不能破坏线程操作的原子性,那么这个时候我们只需要释放对象所持有的锁即可。由于 synchronized 能够锁住任何的对象,因此为了能够保证顺利释放对象,因此 notify 和 wait 便放在了 Object 对象中。
PS: wait 和 notify 必须和 synchronized 关键字一起使用,因为 wait 释放锁的前提是加锁,而 notify 的重新竞争也是在加锁的基础进行的。
线程礼让的方法为 Thread.yield()
方法时暂停当前正在执行的线程,也可理解为线程让出当前的执行时间片给其他线程。在礼让过程中不会释放锁。
在某些情况下,我们需要某个线程等待其他线程执行结束后再继续执行时,我们可以使用 Thread.join()
方法。
join
方法类似于 wait
方法,会释放锁,只不过 join 方法释放的是正在执行的 thread 对象的锁。