Executors.newSingleThreadScheduledExecutor异常后执行停止,不显示任何报错信息


title: 2019-1-14-开发笔记 Executors.newSingleThreadScheduledExecutor
tags: [java]
categories:

  • 开发笔记

Executors.newSingleThreadScheduledExecutor异常后执行停止,不显示任何报错信息

问题

使用newSingleThreadScheduledExecutor作为场景执行器执行任务时,发现客户端没有返回数据,后端日志也没有显示任何异常。

于是,在调用的方法每个阶段打印前调用打log,发现方法执行到一个阶段就停止打印了。

拍卖行竞拍的代码,执行时log只打印 1.

    /**
     *  竞拍物品
     * @param player 玩家
     * @param auctionItem  拍卖品
     * @param price 出价
     */
    private void bidAuctionItem(Player player, AuctionItem auctionItem, int price) {
        log.debug("1");
        Integer auctionMoney = auctionItem.getBiddersMap().get(player.getId());
        log.debug("2");
        if (Objects.isNull(auctionMoney)) {
            //  第一次竞拍
            auctionItem.addBidder(player,price);
            player.moneyChange(price);
        } else {
            auctionItem.addBidder(player,price);
            // 减去继续竞的差价
            player.moneyChange(-(price-auctionItem.getAuctionPrice()));
        }
        log.debug("3");
        notificationManager.notifyPlayer(player,MessageFormat.format("叫价功成。当前拍卖品价格是{0}",
                auctionItem.getAuctionPrice()));
        log.debug("4");
    }

执行这个方法的线程是一个场景执行器,


    private static ThreadFactory sceneThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat("scene-loop-%d").build();
    /** 通过一个场景一个线程处理器的方法保证每个场景的指令循序 */
    ExecutorService singleThreadSchedule = Executors.newSingleThreadScheduledExecutor(sceneThreadFactory);

场景执行器开始执行任务的代码。

    // 玩家在场景内则用场景的执行器执行
    Optional.ofNullable(player).map(Player::getCurrentScene).ifPresent(
        scene -> scene.getSingleThreadSchedule().execute(
                () -> controller.handle(ctx,msg))
    );

原因

在网上查询后发现,在JDK的源码,在源码的Java doc中的发现了如下一句话:

If any execution of the task encounters an exception, subsequent executions are suppressed.Otherwise, the task will only terminate via cancellation or termination of the executor.

也就是说:

如果定时任务执行过程中遇到发生异常,则后面的任务将不再执行。

而且,异常也不会被捕获并打印信息。

解决方案

我的解决方式是直接在执行任务时使用try/catch。

    // 玩家在场景内则用场景的执行器执行
    Optional.ofNullable(player).map(Player::getCurrentScene).ifPresent(
        scene -> scene.getSingleThreadSchedule().execute(
                () -> {
                    log.debug("{}  {} 的 {} 在执行命令 {}",scene.getSingleThreadSchedule(),
                            scene.getName(),player.getName(),new String(msg.getContent()));
                    try {
                        controller.handle(ctx,msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
        })
    );

报错信息终于显示出来了。

结语

这个问题折腾了我好久,方法执行到一半不执行我就猜测是出现了异常,但是异常没有被捕获。这件事教训我以后使用ExecutorService的实现类都要注意异常处理。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值