文章目录
前言
本文介绍 Java 线程中常见的方法,并给出对应的示例,最后简单介绍不推荐使用的方法。
一、常见方法一览
方法名 | static | 说明 | 注意 |
---|---|---|---|
start() | 启动一个新线程,在新的线程运行 run 方法中的代码 | start 方法只是让线程进入就绪,里面代码不一定立刻运行(CPU 的时间片还没分给它)。每个线程对象的 start 方法只能调用一次,如果调用了多次会出现IllegalThreadStateException | |
run() | 新线程启动后会调用的方法 | 如果在构造 Thread 对象时传递了 Runnable 参数,则线程启动后会调用 Runnable 中的 run 方法,否则默认不执行任何操作。但可以创建 Thread 的子类对象,来覆盖默认行为 | |
join() | 等待线程运行结束 | ||
join(long n) | 等待线程运行结束,最多等待 n 毫秒 | ||
isInterrupted() | 判断是否被打断 | 不会清除 打断标记 | |
interrupt() | 打断线程 | 如果被打断线程正在 sleep,wait,join 会导致被打断的线程抛出 InterruptedException,并清除 打断标记 ;如果打断的正在运行的线程,则会设置 打断标记 ;park 的线程被打断,也会设置 打断标记 | |
interrupted() | static | 判断当前线程是否被打断 | 会清除 打断标记 |
sleep(long n) | static | 让当前执行的线程休眠 n 毫秒,休眠时让出 CPU 的时间片给其它线程 | |
yield() | static | 提示线程调度器让出当前线程对 CPU 的使用 | 主要是为了测试和调试 |
二、常见方法示例
1. join 方法
join
方法的作用是让当前线程进入阻塞状态 且不释放 Object
的锁,等待join的线程执行完毕 进入到 TERMINATED
状态之后,再回到就绪状态,继续完成之前的任务。
join
方法常用的有两个重载方法:join()
和 join(long ms)
。
其中带参数的 join
方法表示的是,不用一定得等待到 join 的线程执行完毕,如果已经超过了给定的 ms 毫秒的话,重新进入就绪状态争抢CPU资源。
join 方法的应用案例就是同步,如果当前线程的执行需要依赖其他线程执行完之后的结果,那么我们就可以调用 join
方法让别的线程先运行。
public class JoinDemo implements Runnable{
@Override
public void run() {
try {
System.out.println("我是子线程我先睡一秒");
Thread.sleep(1000);
System.out.println("我是子线程我睡完一秒了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new JoinDemo());
thread.start();
thread.join();
System.out.println("如果不加join方法,我就会先打印出来。");
}
}
2. sleep 方法
Thread.sleep(long ms)
,它的作用是让当前的线程睡眠指定的时间,进入 TIME_WAITTING
状态,在睡眠的期间该线程会释放CPU资源让其他线程去使用CPU,但不会释放同步监视器(锁)。
3. yield 方法
Thread.yield()
,它的作用是让当前的线程放弃CPU资源但不会释放锁,并重新进入 RUNNABLE
状态抢夺CPU资源。
注意:JVM并不一定会同意线程的让步请求,所以通常在生产环境中很少使用该方法。
4. wait 方法
wait
方法的作用是让当前线程释放所有资源(包括CPU资源和锁),进入 WAITTING
状态,在此状态下的线程是不能够自我唤醒的,只能等待其他线程调用 notify
或者 notifyAll
唤醒该线程,被唤醒的线程不会立马获得锁,而是进行就绪状态等待系统的调度。
注意:
wait
方法必须在synchronized
关键字标识的代码块或者方法中调用。- 调用
wait
方法的线程必须拥有同步监视器(锁)。
wait
方法有两种形式:Object.wait()
和 Object.wait(long ms)
对于有参的 wait
方法,该线程会进入 TIME_WAITTING
状态,进入该状态的线程可以被其他线程唤醒或者时间超时自动唤醒。
5. notify 和 notifyAll 方法
Object.notify
方法的作用是唤醒等待队列(WAITTING
状态下或者 TIME_WAITTING
状态下)中的某个线程。
Object.notifyAll
方法则是唤醒等待队列(WAITTING
状态下或者 TIME_WAITTING
状态下)中的所有线程
6. interrupt 方法
interrupt() 方法用于向一个线程发送一个中断请求并将线程的中断标志设置为 true,接受到中断请求的线程可以在合适的时候处理这个中断请求,或者完全不进行处理。
isInterrupted()
:判断当前线程是否已经中断了。不会清空中断状态。interrupted()
:判断当前是否已经中断了,会清空中断状态
6.1 打断正常运行的线程
public class InterruptDemo02 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
log.debug("I'm running!");
boolean interrupted = Thread.currentThread().isInterrupted();
if (interrupted) {
log.debug("我来处理中断请求了");
break;
}
}
}, "t1");
t1.start();
sleep(1);
t1.interrupt();
log.info("中断状态:{}", t1.isInterrupted());
}
}
运行结果:
6.2 打断处于阻塞状态的线程
注意:如果打断的是处于阻塞状态的线程,这时候会抛出一个
InterruptedException
,然后清空中断状态。
public class InterruptDemo01 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
sleep(2);
}, "t1");
t1.start();
sleep(1);
t1.interrupt();
log.debug("中断状态:{}", t1.isInterrupted());
}
}
运行结果:可以看到中断状态被清空为false
了。
三、不推荐的方法
还有一些不推荐使用的方法,这些方法已过时,容易破坏同步代码块,造成线程死锁
方法名 | static | 说明 |
---|---|---|
stop() | 停止线程运行 | |
suspend() | 挂起(暂停)线程运行 | |
resume() | 恢复线程运行 |