logger.info(“开始处理业务逻辑”);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info(“业务逻辑处理完毕”);
guardedObject.setResult(new Object());
});
t1.start();
Object result = guardedObject.getResult();
logger.info(“main线程获取到了返回值{}”,result);
在t1中,为了模拟业务操作,特意让线程sleep了2秒,但是就算是这,主线程依然可以正常获取到返回结果:
接下来,我们加入一个超时机制,为getResult方法添加一个超时时间,如果超过了超时时间,就算是还没有结果,也返回,不再阻塞。
通常的改法是这样的:
这样改造也确实实现了超时的需求,但是不够严谨,因为没法100%保证在没有返回值的情况下,一定可以等足timeOut毫秒。严谨版如下:
我们先假设剩余等待时间就是timeOut
的值,当wait
被唤醒时,先判断timeOut
的值是不是0,如果是0,那么只需要判断result
的值是不是null就可以了。如果不是0,那么计算剩余等待时间,如果剩余等待时间<=0,那就说明真的是超时了,直接break
,如果还有剩余时间,那么判断result
是不是null,如果是null,那么继续wait
,如果不是null,直接返回result
。
接下来我们看下程序的运行结果:
- 假定业务的处理时间还是2秒,main线程设置超时1秒,结果如下:
从结果中可以看到,间隔1秒后main线程停止了阻塞,但是没有获取到返回值。
- 假定业务的处理时间还是2秒,main线程设置超时3秒,结果如下:
从结果中可以看到,虽然设置了超时时间为3秒,但是因为t1在2秒后会设置好result的值,所以main线程也只阻塞了2秒。
- 假定业务的处理时间还是2秒,main线程设置超时0秒,结果如下:
这个的结果跟第2次测试的结果是一样,就不啰嗦了。
引申:
Thread.join
的超时逻辑也是类似的
完整的代码如下:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
@SpringBootTest
class DemoApplicationTests4 {
/**
-
GuardedObject
-
线程t1处理一个事物,主线程等待获取事物的处理结果
-
@throws InterruptedException
*/
@Test
void Test1() throws InterruptedException {
Logger logger = LoggerFactory.getLogger(this.getClass());
GuardedObject guardedObject = new GuardedObject();
Thread t1 = new Thread(()->{
logger.info(“开始处理业务逻辑”);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info(“业务逻辑处理完毕”);
guardedObject.setResult(new Object());
});
t1.start();
logger.info(“main线程开始获取返回值”);
Object result = guardedObject.getResult(TimeUnit.SECONDS.toMillis(0));
logger.info(“main线程获取到了返回值{}”,result);
}
/**
- 守护对象
*/
static class GuardedObject{
private Object result;
private final Object lock = new Object();
public Object getResult(long timeOut) {
long currentTimeMillis = System.currentTimeMillis();
long remainingTime = timeOut;
synchronized (lock){
while (result==null){
try {
lock.wait(remainingTime);
if (timeOut!=0) {
remainingTime = timeOut-(System.currentTimeMillis()-currentTimeMillis);
if (remainingTime<=0) {
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return result;
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
码字不易,觉得有帮助的可以帮忙点个赞,让更多有需要的人看到
又是一年求职季,在这里,我为各位准备了一套Java程序员精选高频面试笔试真题,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考
以下是部分内容截图
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考
以下是部分内容截图
[外链图片转存中…(img-s8pU1FUg-1713670606844)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!