文章目录
- 前言
- 思路
- 总结
前言
这是蘑菇街一面面试官问我的一个问题。他说:如果有这么一个场景,我执行业务的时候,不想让业务执行时间超过一定时间,如果超出就停止执行,你怎么来设计!
思路
我们在学习Java并发编程的时候,那些常见的方法大多都有设置超时时间的参数,我们可以根据这一思路来设计超时结束任务的方案。我这里用到的是Thread.join()方法,先来解释下join方法吧。
join()方法:如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时时间里没有终止,那么将会从该超时方法中返回。摘自《Java并发编程的艺术》
我们来看下join的源码:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
//正常来说,我们会进入到这里,进入到循环里,直到调用join方法的线程执行完毕之后或者超出时间限制了,才退出。
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
其实我感觉书中对join的解释还是有那么一点欠缺的,我认为是:当在主线程A中调用另一个线程B的join方法意味着,从一开始的A、B两个线程并发执行变为串行执行的了,也就是将B线程插入到A线程中,然后等待B线程执行完成以后,再执行剩下的A线程的任务了。如果这个join方法带有超时参数的话,可以理解为,在这段时间内,A等待B线程执行(串行),一旦超出这个时间,两个线程又会回到并发执行的状态了。
回到我们之前的问题 ,我们想设计一个超时退出的接口,就可以利用这个带有超时参数的join来实现,来看看我的代码,注意看注释。
package com.markus.basic.Java多线程.方法超时问题;
/**
* Author:markusZhang
* Date:Create in 2020/10/8 12:57
* todo:
*/
public class JoinDemo {
public static void main(String[] args){
Thread method = new Thread(new ThreadMethod());
//调用方法
method.start();
try {
method.join(2000);//规定业务接口执行不能超过的时长
} catch (InterruptedException e) {
e.printStackTrace();
}
method.interrupt();//调用中断很重要,如果不调用的话,就会回到上面说的,两个线程并发执行,就起不到效果了。
}
}
class ThreadMethod implements Runnable{
@Override
public void run() {
try {
Thread.sleep(3000);//执行业务
System.out.println("方法调用完成");
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("方法调用超时");
}
}
}
总结
当然了,设计任务执行超时退出有很多种方案,这个只是其中一种。在开发中,我们需要多注意下那些带有超时参数的方法,说不定也是可以设计的。