开卷有益 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多线程处理某个线程超时的问题的更多相关文章

  1. java中异步多线程超时导致的服务异常

    在项目中为了提高大并发量时的性能稳定性,经常会使用到线程池来做多线程异步操作,多线程有2种,一种是实现runnable接口,这种没有返回值,一种是实现Callable接口,这种有返回值. 当其中一个线 ...

  2. 【Java基础】线程和并发机制

    前言 在Java中,线程是一个很关键的名词,也是很高频使用的一种资源.那么它的概念是什么呢,是如何定义的,用法又有哪些呢?为何说Android里只有一个主线程呢,什么是工作线程呢.线程又存在并发,并发 ...

  3. Java总结之线程(1)

    java线程是很重要的一项,所以作为java程序员必须要掌握的. 理解java线程必须先理解线程在java中的生命周期.. 1.java线程生命周期 1.new  创建一个线程  java中创建线程有 ...

  4. 第9章 Java中的线程池 第10章 Exector框架

    与新建线程池相比线程池的优点 线程池的分类 ThreadPoolExector参数.执行过程.存储方式 阻塞队列 拒绝策略 10.1 Exector框架简介 10.1.1 Executor框架的两级调 ...

  5. Java并发之线程转储

    一.java线程转储 java的线程转储可以被定义为JVM中在某一个给定的时刻运行的所有线程的快照.一个线程转储可能包含一个单独的线程或者多个线程.在多线程环境中,比如J2EE应用服务器,将会有许多线 ...

  6. Java并发之线程池ThreadPoolExecutor源码分析学习

    线程池学习 以下所有内容以及源码分析都是基于JDK1.8的,请知悉. 我写博客就真的比较没有顺序了,这可能跟我的学习方式有关,我自己也觉得这样挺不好的,但是没办法说服自己去改变,所以也只能这样想到什么 ...

  7. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  8. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

  9. Java并发之——线程池

    一. 线程池介绍 1.1 简介 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡 ...

随机推荐

  1. Clickhouse v18编译记录

    简介 ClickHouse是"战斗民族"俄罗斯搜索巨头Yandex公司开源的一个极具"战斗力"的实时数据分析数据库,是面向 OLAP 的分布式列式DBMS,圈内 ...

  2. Win7 64位下安装64bit MS SQL Server2005时安装不了Reporting Services的处理办法

    警告截图: 解决办法: 在cmd窗口运行如下脚本即可: "cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/A ...

  3. Highcharts入坑记

    第一次用Highcharts画一个温度湿度变化的图片,因为不熟悉跳了好多坑,特记录下: 一.JS引用 <script src="~/Scripts/jquery.min.js" ...

  4. AngularJS学习之旅—AngularJS Table(十一)

    1.AngularJS 表格 1. ng-repeat 指令可以完美的显示表格 AngularJS 实例 <!DOCTYPE html> <html> <head> ...

  5. 使用jquery实现选项卡切换效果

    几张简陋的框架效果图 页面加载时: 选项卡操作后: css样式: <style type="text/css"> *{margin:0px;padding:0px;} ...

  6. Windows系统资源监控

    1.windows自带系统资源监控工具 2.Windows监控的数据来源:Performance Counters 2.1 Performance Counter架构 2.2 Performance ...

  7. 本机不安装Oracle客户端,使用PL/SQL Developer和 Instant Client 工具包连接oracle 11g远程数据库

    一.先到Oracle网站下载Instant Client 下载地址:http://www.oracle.com/technetwork/cn/database/features/instant-cli ...

  8. 【Teradata UDF】中文按字符查找chs_instr

    一.场景描述 数据库为ASCII编码单字节存储,在查询中文时可能会出现错误结果.例如查询like“房”字,会查询出不含“房”,含“朔科”的结果. select * from Tablename01 w ...

  9. ASP.NET MVC学习系列(4)——MVC过滤器FilterAttribute

    1.概括 MVC提供的几种过滤器其实也是一种特性(Attribute),MVC支持的过滤器类型有四种,分别是:AuthorizationFilter(授权),ActionFilter(行为),Resu ...

  10. Linux-基础学习(四)-部署图书管理系统项目

    部署图书管理项目需要以下软件 项目文件(django项目文件夹) 数据库文件(django项目对应的数据库文件) centos7(linux本体) nginx(反向代理以及静态文件收集) uWSGI( ...