取消当前任务并在java

时间:2017-07-10 19:08:47

标签: java multithreading performance threadpoolexecutor java-threads

请花点时间阅读以下内容。我们将非常感谢您的帮助

我有一个场景需要监控一些实时活动。比如说一个方法在毫秒内实时调用。我必须监视好像首次调用该方法以及何时最后调用该方法。

所以,在最后一次击中该方法后,我需要等待一段时间,比如10秒,看看它是否在那段时间内没有再次调用。如果没有调用那么我需要运行一些代码。

我想使用 ExecuterService 并使用 newCachedThreadPool()。但我对如何实现这一点很困惑。

如果您不确定我在说什么,请举一些例子说,当有网络故障时,你接收到心跳并突然停止接收它,然后你在屏幕上显示一些错误消息,例如:连接不可用。在我的情况下,它的一些第三方应用程序正在发送一些消息,它只是单向通信。就像,我的应用程序发送了一些请求,其他应用程序继续发送响应。因此,我需要监控该响应,并以某种方式需要知道我何时收到最后一个响应。

我的方法 - 我想在每次调用该方法时执行一个任务,该方法将等待10秒并且在10秒内,如果再次调用该方法,它将以某种方式取消当前任务并将创建另一个任务(或重用,如果可能),这将再次运行10秒。这将继续发生,直到收到最后一条消息(当方法最后被调用时),然后一旦10秒延迟结束,任务将被执行,一些代码将运行以在UI上显示错误消息。

我之前使用过Timer,它解决了这个问题但创建了一个性能问题,因为新的Timer会在每次收到新消息时实例化一个新的TimerTask,因此会产生很多垃圾收集器无法快速回收的对象,因此导致outOfMemorry错误并使服务器无响应。显然这是一个糟糕的代码,这就是我在这里求助的原因。

请帮我解决这个问题。

3 个答案:

答案 0 :(得分:1)

如果您使用最基本的工具来处理它,这很容易 - 有时候遇到简单的问题,线程池之类的增强工具会分散注意力。

假设您有一个简单的线程(Runnable)。该线程检查时间戳以查看该时间戳是否为10秒。如果是你通知你的听众,如果没有,你会延迟几毫安并再次检查。

现在你所要做的就是每次运行时将(volatile)时间戳更新为“now”。可能会有一些其他业务规则在这里实施,但它应该是一个很好的基础。

现在唯一的问题是你如何通知你的听众。如果这种情况很少发生,你可以在你正在检查时间的同一个线程上调用它们 - 但我认为你已经排除了这一点。如果它经常发生但您不希望/需要它“嵌套”您的通知,您可以暂停第二个线程,除非在您的观察者线程触发时通知客户端。

如果您需要“嵌套”通知(在原始通知返回之前通知侦听器),那么您需要一个线程池来通知您的通知。

最后我想如果你想抓住你的计时器没有被调用10秒但你不想嵌套,你的计时线程可以将“事件”推送到线程安全队列而你的“通知”线程可以将它们拉下来并一次发送一个事件。

这应该涵盖所有可能性。

答案 1 :(得分:0)

答案 2 :(得分:-1)

java.util.concurrent.Executors.newCachedThreadPool

  

创建一个线程池,根据需要创建新线程,但是会   在先前构造的线程可用时重用它们。这些   池通常会提高执行程序的性能   许多短暂的异步任务。执行调用将重用   以前构造的线程(如果有)如果没有现有的线程   可用时,将创建一个新线程并将其添加到池中。主题   未使用60秒的任务将被终止并删除   从缓存。因此,一个长时间闲置的游泳池将会   不消耗任何资源。请注意具有相似属性的池   可以创建不同的细节(例如,超时参数)   使用ThreadPoolExecutor构造函数

由于您有许多短期任务,因此缓存线程池是最佳选择。

简短的例子:

public class WorkerThread implements Runnable {

    private String command;

    public WorkerThread(String s){
        this.command=s;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
        processCommand();
        System.out.println(Thread.currentThread().getName()+" End.");
    }

    private void processCommand() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString(){
        return this.command;
    }
}

运行WorkerThread使用:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();

Runnable worker = new WorkerThread("threadName");
            executor.execute(worker);

停止WorkerThread使用:

executor.shutdown();