在调用 EJB 方法时中断客户端线程的正确方法是什么?

发布于 2024-10-20 14:12:09 字数 605 浏览 4 评论 0原文

我有一个 java 客户端,它在新线程中管理其服务器调用,以防止 GUI 冻结。

即使在许多地方都阻止了这种情况,该方法也可能会在同一模型上再次调用,例如使用不同的参数。在这种情况下,我显然希望具有最新参数的最新调用成为“成功”并显示其结果的调用。

我有一个系统,它跟踪先前启动的线程,并在启动新线程之前中断它(Thread.interrupt())。然后,其他方法在将新结果发送到 GUI 元素之前检查它们是否在非中断线程中运行(使用 if (Thread.currentThread().isInterrupted()))。

此结构是使用以前的服务器连接器,因为我是唯一检查进程上的中断标志的人,我的问题是我现在在客户端中使用 EJB 方法调用,并且它们对中断的线程反应很糟糕。 EJB 调用期间的线程将触发 RuntimeException,其中包含 InterruptedException

显然,我可以在每个服务器中捕获 RuntimeException 。调用并检查它们的中断原因,但它似乎不是很“干净”。

我的问题是:在这种情况下我可以做什么?中断运行 EJB 方法调用的线程的正确方法是什么?

I have a java client which is managing its server calls in new threads to prevent the GUI from freezing.

Even if this is prevented in many places, it is possible that the method will be called again on the same model, for example with different parameters. In such case, I obviously want the newest call, with the most up to date parameters, to be the one "succeeding" and displaying its results.

I have a system which is keeping track of the previously launched Thread, and interrupts it before launching the new one (Thread.interrupt()). The other methods are then checking if they are running in a non-interrupted thread (using if (Thread.currentThread().isInterrupted()) before firing the new results to the GUI elements.

This structure was working with a previous connector to the server, as I was the only one checking the interrupt flag on the process. My problem is that I'm now using EJB method calls in the client, and they react badly to the interrupted thread. Interrupting the Thread during an EJB call will trigger a RuntimeException which is including an InterruptedException. And it doesn't seem like a normal thing to happen.

Obviously I could catch RuntimeExceptions in every server call and check their cause for the interrupt, but it doesn't seem very "clean".

My question is: what can I do in such context? What is the proper way to interrupt a Thread running an EJB method call?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

反目相谮 2024-10-27 14:12:09

既然您不介意过时的 EJB 调用在服务器上继续,为什么不允许调用线程“自然”终止而是丢弃结果,因为它的调用已被另一个线程取代?我没有时间提供示例实现,但您可能会发现使用 Future 和相关的 Java 并发类取得了一些进展。

编辑

除此之外,您可能会发现类似的方法可以解决问题,但对我来说这感觉很老套,我相信还有更优雅的解决方案。

在调用线程上(可能是按钮的 onclick 方法):

AsynchronousResultManager.registerRequest("UNIQUE_IDENTIFIER", runnableExecuteRequest);

registerRequest 会执行类似以下操作:

registerClick(String id, Runnable execution) {
    AtomicReference ref = executions.get(id); //executions is a Map<String, AtomicReference> created as a a computing map by Guava MapMaker
    execution.setReference(ref); //so that the Runnable has a reference to it later
    ref.set(execution); //this will overwrite an existing reference to a previous invocation.
    //here you need to actually kick off your thread in whatever way works best for you
}

执行请求的 runnable 将是以下子类:

public abstract class RequestRunnable implements Runnable {

    private AtomicReference ref;

    public void run() {
        doRunInternal(); //actually go off and do the request to the J2EE server
        if (this == ref.get()) { //ie if the current runnable is the same as in the reference, we can proceed to actually dispatch the result
            dispatchResult(); //this method would do something like add a runnable to the SwingWorkerThread
        }
    }

    protected abstract void doRunInternal();
    protected abstract void dispatchResult();

    public void setReference(AtomicReference ref) {
        this.ref = ref;
    }

}

这可能会崩溃和燃烧,但希望它能引导你进行调查......

Seeing as you don't mind the obsolete EJB call continuing on the server, why not allow the calling thread to terminate 'naturally' but to discard the result because its call has been superceded by another thread? I don't have time to provide a sample implementation, but you may find that you get some mileage with Futures and the related Java concurrency classes.

Edit

Further to this, you may find something like this would do the trick, but it feels hacky to me and I'm sure there are more elegant solutions.

On the calling thread (perhaps the onclick method of a button):

AsynchronousResultManager.registerRequest("UNIQUE_IDENTIFIER", runnableExecuteRequest);

The registerRequest would do something like:

registerClick(String id, Runnable execution) {
    AtomicReference ref = executions.get(id); //executions is a Map<String, AtomicReference> created as a a computing map by Guava MapMaker
    execution.setReference(ref); //so that the Runnable has a reference to it later
    ref.set(execution); //this will overwrite an existing reference to a previous invocation.
    //here you need to actually kick off your thread in whatever way works best for you
}

The runnable that executes the request would be a subclass of:

public abstract class RequestRunnable implements Runnable {

    private AtomicReference ref;

    public void run() {
        doRunInternal(); //actually go off and do the request to the J2EE server
        if (this == ref.get()) { //ie if the current runnable is the same as in the reference, we can proceed to actually dispatch the result
            dispatchResult(); //this method would do something like add a runnable to the SwingWorkerThread
        }
    }

    protected abstract void doRunInternal();
    protected abstract void dispatchResult();

    public void setReference(AtomicReference ref) {
        this.ref = ref;
    }

}

This will probably crash and burn, but hopefully it points you down a line of enquiry...

三岁铭 2024-10-27 14:12:09

要停止线程,您需要执行 2 种操作:

  • 如果线程正在等待阻塞操作(IO、网络、锁定...),您需要中断它。将抛出 InterruptedException,使正在运行的代码有机会捕获异常并以适当的方式停止。
  • 如果线程只是做一些处理,Thread.interrupt() 将无济于事。不会引发任何异常,线程将继续其处理。处理代码需要定期检查您是否仍希望该过程继续进行。

无论如何,要正确执行此操作,您需要由要停止的线程运行的代码处理这两种情况。这里没有灵丹妙药。

To stop a thread you need to perform 2 sort of actions :

  • if the thread is waiting for a blocking operation (IO, network, lock...) you need to interupt it. An InterruptedException will be thrown giving the running code the opportunity to catch the exception and to halt in a proper way.
  • If the thread is just doing some processing, Thread.interrupt() will not help. No exception will be thrown and the thread will simply continue it's processing. The processing code will need to check on a regular basis that you still want the process to continue.

In any case, to do it properly, you need that the code that is run by your thread that you want to stop deal with the both cases. No silver bullet here.

甜警司 2024-10-27 14:12:09

考虑到现有的体系结构,我最终从每个服务器调用中捕获 RuntimeException,形式如下:

try {
    return getEJBService().getServiceResult(param, param, param);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof InterruptedException)
        throw (InterruptedException)cause;
    else
        throw e;
}

它并不是很漂亮,但至少它允许我根据当前模型的中断进行操作。

在理想的世界中,人们应该选择 Rich 给出的解决方案之一。

Given the existing architecture, I finally went with catching the RuntimeException from each server call, in such form:

try {
    return getEJBService().getServiceResult(param, param, param);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof InterruptedException)
        throw (InterruptedException)cause;
    else
        throw e;
}

It's not really pretty, but at least it allows me to act according to the interruption with my current model.

In the ideal world, one should rather go with one of the solutions given by Rich.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文