miki艾比利的博客

愿居于一城,与卿所见美好......

您现在的位置是:首页>漫生活>详细内容

解决getConnection或者java.sql.rs.next() 时,线程hang住,导致代码卡顿问题

发布时间:2019-10-24 21:19:07 编辑:miki艾比利浏览(452)评论(0)

    1. 问题复现

    当你兴高采烈的写完一堆获取数据库连接的代码准备测试时,由于服务器性能,或者网络问题,导致线程阻塞,页面卡死。大多数数据库可能会具备连接超时的设置,你可以设置一下连接超时,自动退出即可。但是,有的数据库就是那么尿性,又或者是本身提供的jdbc驱动不支持连接超时设置,这个时候就很头疼了,每次页面查询数据或者点击测试连接的时候,让前台写一堆ajax超时设置吗,好了,废话不多说,此处教你一个方法,使用java中的ExecutorService来实现任务的中止。

    ExecutorService简介:

    查看java的api可知,

    继承于Executor,提供了管理终止的方法和可以生成Future,用来跟踪一个或多个异步任务进度的方法。

    可以关闭Service,之后会拒绝执行新的任务。提供了两种终止方法,shutdown()会终止任务,但是shutdown()之前提交的任务会继续执行,而shutdownNow()会终止掉没启动的任务并且终止正在运行的任务。终止的时候如果没有提交的任务,没有等待的任务,没有正在执行的任务时,应该释放executor资源。

    总的来说,实现ExecutorService,就有终止任务,和生成Future跟踪任务的能力。

    3.代码

    下面上代码:

    public static void main(String[] args) {
    		
    		boolean hasNext = false;
    		
    		Runnable runnable = new Runnable() {
                public void run() {
                    try {
                       Thread.sleep(5000);
                       System.out.println("乐乐");
                    } catch (Throwable e) {
                        
                    }
                }
            };
    //      Thread thread = new Thread(runnable);
    //      thread.start();
            
            System.out.println("tomcat初始化..");
            System.out.println("开始时间:"+System.currentTimeMillis());
            
            //首先构造Executor接口,下面的例子是创建一个单线程的执行者,你也可以根据需要创建基于线程池的执行者
            ExecutorService executor = Executors.newSingleThreadExecutor();
            
            //将rs.next()或者getcConnection方法委托给Callable接口去调用,通过Future接口获取返回结果
    		FutureTask future = new FutureTask(new Callable() {
    			public Boolean call() throws IOException {
    				try {
    					//模拟超时
    					Thread.sleep(5000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();return false;
    				}
    				System.out.println("获取连接成功..");
    				return true;
    			}
    		});
    		
    		try {
    			executor.execute(future);
    			hasNext = future.get(2, TimeUnit.SECONDS);
    		} catch (InterruptedException | ExecutionException | TimeoutException e) {
    			e.printStackTrace();
    			System.out.println("超时啦...");
    			//捕获异常后,关闭当前任务!!!重要  2019.10.24  miki
    			executor.shutdown();
    		}       
            if(hasNext) {
            	//System.out.println("到达时间:"+System.currentTimeMillis());
            	System.out.println("到达时间:"+System.currentTimeMillis());
            }      
            
    	}

    执行结果如下:

    注意如下:

    shutdown()

    不能添加新任务,否则抛异常。但是已存在的任务会继续执行完成。(所以才会打印出来获取链接成功

    shutdownNow()

    不接收新任务,不处理等待任务,尝试中断已存在线程(通过Thread.interrupt(),这个方法作用有限,你的任务里没有抛出InterruptException的话,就中断不了了)

    Future submit(Callable task);

    Future submit(Runnable task, T result);

    谢谢观看,记得掉个赞哦

     

关键字词:ExecutorService#获取连接卡住