6

KeyedDataQueue在使用 JTOpen类提供的 read() 方法时,我发现了一个奇怪的行为。

我设置了 90 秒的超时时间,当达到超时时间时,99% 的读取执行将恢复我的调用方法执行。

至于其他 1% 超时未考虑/达到,我的调用方法保持挂起......

经过一番搜索,我发现了这篇文章:

http://archive.midrange.com/java400-l/201112/msg00056.html

基本上它证实了我的怀疑:

“我还发现 DataQueue.read() 超时功能是服务器端的,所以如果 TCP/IP 连接被静默断开(我相信这是造成这种情况的根本原因),它仍然会挂起。”

我正在使用 7.2 版的 JTOpen,我意识到 7.9 版已经发布了。我没有更新到 7.9,因为我有很多使用稳定的 7.2 的关键应用程序,实际上这是第一个让我考虑更新到 7.9 的真实场景。

为了帮助我做出这个决定,我真的很想得到你的反馈,尤其是那些遇到这种情况并最终通过升级 JTOpen 解决它的人。

具体来说,是否有解决此问题的方法,升级 JTOpen 是否对此有帮助?将 JTOpen 升级到 7.9 会破坏 7.2 中的任何工作吗?

4

1 回答 1

1

如上所述,数据队列读取超时是服务器端的。如果 iSeries 和客户端之间的 TCP 连接停止或断开,客户端将等待套接字超时。我的解决方案是建立一个故障安全中断器来阻止停滞的读取。这是如何完成此操作的快速代码示例。

    public class DataQueueListenerExample {
    //This executes our Interrupter after the specified delay.
    public final ScheduledThreadPoolExecutor interruptExecuter = new ScheduledThreadPoolExecutor(1);
    //the dataqueue object.
    protected DataQueue dataqueue;

    public DataQueueEntry read(int wait)
    {
        ScheduledFuture<?> future = null;
        try {
            //create our fail safe interrupter. We only want it to 
            //interrupt when we are sure the read has stalled. My wait time is 15 seconds
            future = createInterrupter(wait * 2, TimeUnit.SECONDS);
            //read the dataqueue
            return this.dataqueue.read(wait);
        } catch (AS400SecurityException e) {
        } catch (ErrorCompletingRequestException e) {
        } catch (IOException e) {
        } catch (IllegalObjectTypeException e) {
        } catch (InterruptedException e) {
            //The read was interrupted by our Interrupter
            return null;
        } catch (ObjectDoesNotExistException e) {
        } finally{
            //Cancel our interrupter
            if(future != null && !future.isDone())
                future.cancel(true);
            Thread.interrupted();//clear the interrupted flag

            interruptExecuter.shutdown();
        }
        return null;
    }


    public ScheduledFuture<?> createInterrupter(long timeout,TimeUnit timeunit)
    {
        return interruptExecuter.schedule(new Interrupter(),timeout,timeunit);
    }

    class Interrupter implements Runnable
    {
        final Thread parent;
        Interrupter()
        {
            this.parent = Thread.currentThread();
        }

        @Override
        public void run() {
            parent.interrupt();
        }
    }
    }

我强烈建议在出现 InterruptedException 后在新的 AS400 连接上重新创建 DataQueue 对象。您的 AS400 连接可能会停止。Thread.interrupt 非常有用,但请谨慎使用。

于 2014-01-08T15:59:11.570 回答