Java多线程处理某个线程超时的问题
开卷有益 union/substact/intersect/difference
Java线程池处理子线程超时问题
起因
近几天,某个正常运行了近两个月的项目,单日处理请求条数锐减,排查日志发现如下异常:
Mon Apr 29 18:12:01 CST 2019, org.apache.hadoop.hbase.client.RpcRetryingCaller@34f04eb2, java.io.IOException: java.io.IOException: Could not seek StoreFileScanner[HFileScanner for reader reader=hdfs://Ucluster5/hbase/data/default/video_search_shot/5402a6d8800f28541d456a50367cc757/d/b98d69cfc81f4903a3ddb94e95114454, compression=none, cacheConf=CacheConfig:enabled [cacheDataOnRead=true] [cacheDataOnWrite=false] [cacheIndexesOnWrite=false] [cacheBloomsOnWrite=false] [cacheEvictOnClose=false] [cacheCompressed=false], firstKey=8bfc17007695e96ae27e049a11b42792:11.000_0.133/d:dhash128/1554703137033/Put, lastKey=8e00dfe4801a80988f7fe7944120317b:14.000_1.000/d:video/1554768240786/Put, avgKeyLen=65, avgValueLen=398, entries=356358, length=168414223, cur=null] to key 8de584f3a3f112d2cbe581f1f8e30588:0.000_1.000/d:/LATEST_TIMESTAMP/DeleteFamily/vlen=0/mvcc=0
at org.apache.hadoop.hbase.regionserver.StoreFileScanner.seek(StoreFileScanner.java:157)
at org.apache.hadoop.hbase.regionserver.StoreScanner.<init>(StoreScanner.java:168)
at org.apache.hadoop.hbase.regionserver.HStore.getScanner(HStore.java:1648)
at org.apache.hadoop.hbase.regionserver.HRegion$RegionScannerImpl.<init>(HRegion.java:3513)
at org.apache.hadoop.hbase.regionserver.HRegion.instantiateRegionScanner(HRegion.java:1816)
at org.apache.hadoop.hbase.regionserver.HRegion.getScanner(HRegion.java:1808)
at org.apache.hadoop.hbase.regionserver.HRegion.getScanner(HRegion.java:1785)
at org.apache.hadoop.hbase.regionserver.HRegion.get(HRegion.java:4538)
at org.apache.hadoop.hbase.regionserver.HRegion.get(HRegion.java:4513)
at org.apache.hadoop.hbase.regionserver.HRegionServer.get(HRegionServer.java:2780)
at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:26925)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2141)
at org.apache.hadoop.hbase.ipc.RpcServer$Handler.run(RpcServer.java:1844)
Caused by: java.io.IOException: Failed to read compressed block at 159280276, onDiskSizeWithoutHeader=67484, preReadHeaderSize=33, header.length=33, header bytes: DATABLK*\x00\x01\x07:\x00\x01\x07&\x00\x00\x00\x00\x07\x97\x02\xD9\x01\x00\x00@\x00\x00\x01\x07G
at org.apache.hadoop.hbase.io.hfile.HFileBlock$FSReaderV2.readBlockDataInternal(HFileBlock.java:1495)
at org.apache.hadoop.hbase.io.hfile.HFileBlock$FSReaderV2.readBlockData(HFileBlock.java:1358)
at org.apache.hadoop.hbase.io.hfile.HFileReaderV2.readBlock(HFileReaderV2.java:335)
at org.apache.hadoop.hbase.io.hfile.HFileBlockIndex$BlockIndexReader.loadDataBlockWithScanInfo(HFileBlockIndex.java:253)
at org.apache.hadoop.hbase.io.hfile.HFileReaderV2$AbstractScannerV2.seekTo(HFileReaderV2.java:474)
at org.apache.hadoop.hbase.io.hfile.HFileReaderV2$AbstractScannerV2.seekTo(HFileReaderV2.java:495)
at org.apache.hadoop.hbase.regionserver.StoreFileScanner.seekAtOrAfter(StoreFileScanner.java:225)
at org.apache.hadoop.hbase.regionserver.StoreFileScanner.seek(StoreFileScanner.java:145)
... 12 more
Caused by: java.io.IOException: Invalid HFile block magic: \x00\x00\x00\x00\x00\x00\x00\x00
at org.apache.hadoop.hbase.io.hfile.BlockType.parse(BlockType.java:154)
at org.apache.hadoop.hbase.io.hfile.BlockType.read(BlockType.java:165)
at org.apache.hadoop.hbase.io.hfile.HFileBlock.<init>(HFileBlock.java:258)
at org.apache.hadoop.hbase.io.hfile.HFileBlock$FSReaderV2.readBlockDataInternal(HFileBlock.java:1492)
... 19 more
协调大数据与运维部门,最终定位错误为Hadoop集群某个节点磁盘坏块,随后运维更换磁盘,速度略微提升,该异常仍然存在(最终排查确认仍有其他节点磁盘坏块,全部更换后问题解决).这就造成一个问题,业务代码操作video_search_shot这张表时,将因此阻塞,时长达到数分钟.考虑到磁盘坏块客观存在,数据库连接超时过久,故设置线程超时时间成了必然选择.
线程超时解决方案
常用的线程超时处理方法有很多,例如Thread.join(long timeout)/Future.get(long timeout,TimeUnit unit)/ExecutorService的超时方法...实际应用中,偏爱使用第二种 Future.get(long timeout,TimeUnit unit),因为其相对来说更灵活,关键是该类更熟悉,而且相对于针对线程池的超时处理,该方案处理粒度更小,便于掌控.
实操
既然选择使用Future的get方法去处理线程超时问题,这里就需要考虑线程池子线程的处理时机,在调用get方法时,子线程应处于未执行状态,否则超时处理就没有意义.故排除ExecutorService.invokeAll(Collection<? extends Callable<T> tasks>)/ExecutorService.invokeAny(Collection<? extends Callable<T> tasks>)及二者对应的线程池超时方法.这时往线程池提交子线程的选择就剩下了ExecutorService.submit(....),其次,需要处理的异常,首先是TimeoutException,其次是,InterruptedIOException,因为将调用Future.cancel(boolean mayInterruptIfRunning)方法中断子线程.
代码
ExecutorService exec = Executors.newFixedThreadPool(4);
List<Future<Boolean>> futures = new ArrayList<>();
Callable<Integer> task;
for (int i = 0;i<4;i++) {
task = () -> {
TimeUnit.SECONDS.sleep(50);
return true;
};
Future<Boolean> futureNow = exec.submit(task);
futures.add(futureNow);
} for (Future<Integer> future :
futures) { try {
Integer intRes = future.get(2000, TimeUnit.MILLISECONDS);
System.out.println("result : " + intRes);
} catch (InterruptedException ex) {
System.out.println("子线程被中断 ");
} catch (ExecutionException e) {
System.out.println("子线程执行出错");
} catch (TimeoutException e) {
System.out.println("处理超时");
} finally {
future.cancel(true); // 中断子线程
}
}
exec.shutdown();
Java多线程处理某个线程超时的问题的更多相关文章
- java中异步多线程超时导致的服务异常
在项目中为了提高大并发量时的性能稳定性,经常会使用到线程池来做多线程异步操作,多线程有2种,一种是实现runnable接口,这种没有返回值,一种是实现Callable接口,这种有返回值. 当其中一个线 ...
- 【Java基础】线程和并发机制
前言 在Java中,线程是一个很关键的名词,也是很高频使用的一种资源.那么它的概念是什么呢,是如何定义的,用法又有哪些呢?为何说Android里只有一个主线程呢,什么是工作线程呢.线程又存在并发,并发 ...
- Java总结之线程(1)
java线程是很重要的一项,所以作为java程序员必须要掌握的. 理解java线程必须先理解线程在java中的生命周期.. 1.java线程生命周期 1.new 创建一个线程 java中创建线程有 ...
- 第9章 Java中的线程池 第10章 Exector框架
与新建线程池相比线程池的优点 线程池的分类 ThreadPoolExector参数.执行过程.存储方式 阻塞队列 拒绝策略 10.1 Exector框架简介 10.1.1 Executor框架的两级调 ...
- Java并发之线程转储
一.java线程转储 java的线程转储可以被定义为JVM中在某一个给定的时刻运行的所有线程的快照.一个线程转储可能包含一个单独的线程或者多个线程.在多线程环境中,比如J2EE应用服务器,将会有许多线 ...
- Java并发之线程池ThreadPoolExecutor源码分析学习
线程池学习 以下所有内容以及源码分析都是基于JDK1.8的,请知悉. 我写博客就真的比较没有顺序了,这可能跟我的学习方式有关,我自己也觉得这样挺不好的,但是没办法说服自己去改变,所以也只能这样想到什么 ...
- Java中创建线程的三种方式以及区别
在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...
- Java多线程(五) —— 线程并发库之锁机制
参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...
- Java并发之——线程池
一. 线程池介绍 1.1 简介 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡 ...
随机推荐
- 深海中的STL—mt19937
mt19937 当你第一眼看到这玩意儿的时候 肯定禁不住吐槽:纳尼?这是什么鬼? 确实,这个东西鲜为人知,但是它却有着卓越的性能 简介 mt19937是c++11中加入的新特性 它是一种随机数算法,用 ...
- zabbix server3.4 使用mailx配置邮件报警
软件具体配置如下: 操作系统:Centos7.5 zabbix server版本:zabbix server3.4 zabbix agent版本:zabbix agent3.0 现在开始配置zabbi ...
- TextView走马灯
设置textView走马灯形式显示: android:marqueeRepeatLimit="marquee_forever" android:scrollHorizontally ...
- Docker for Win10中文乱码问题
environment:win10 docker+centos7+nginx1.9.9 issue:在docker运行nginx(centos),volume本地html目录挂载到nginx的htm ...
- ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用
一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual ...
- 如何利用Vagrant快速搭建相同配置的开发环境?
作为一名程序猿,我们常常会遇到需要搭建开发环境的问题,特别是在新入职的时候,sublime, node, apache, mysql, php等等以及各种框架的安装.如果入职的是大公司有可能这些必要的 ...
- SQL Server实际执行计划COST"欺骗"案例
有个系统,昨天Support人员发布了相关升级脚本后,今天发现系统中有个功能不能正常使用了,直接报超时了(Timeout expired)的错误.定位到相关相关存储过程后,然后在优化分析的过程中,又遇 ...
- c/c++ 多线程 boost的读写(reader-writer)锁
多线程 boost的读写(reader-writer)锁 背景:保护很少更新的数据结构时,c++标准库没有提供相应的功能. 例如:有个DNS条目缓存的map,基本上很少有更新,大部分都是读取,但是偶尔 ...
- chome(谷歌浏览器)上传文件崩溃/上传图片崩溃/打开浏览文件未响应 解决方案
测试解决方案:关闭搜狗输入法(我用的是搜狗输入法,若使用其他输入法,此方案也可能适用),再测试是否重现浏览器崩溃问题 可选解决方案:升级搜狗输入法(如果想 卸载输入法 也可以) 前面有段时间chome ...
- Java学习笔记记录(二)
1.复合语句 if条件语句 使用场景:boolean类型判断.一个范围的判断.几个常量值的判断 有左大括号就没有分号,有分号就没有左大括号. 如下: public class demo1 { stat ...