繁体   English   中英

在Java中创建另一个任务时取消当前任务并重用同一线程

[英]cancelling current task and reuse the same thread while creating another task in java

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

我有一个需要监视一些实时活动的场景。 假设某个方法在毫秒内被实时调用。 我必须监视好像第一次调用该方法以及何时最后调用该方法。

因此,在该方法被最后击中之后,我需要等待一段时间,例如10秒钟,然后查看在该时间内是否没有再次调用它。 如果未调用,则需要运行一些代码。

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

如果您不确定我在说什么,请举个例子,例如,当网络出现故障时,并且u在接收到心跳信号时突然突然停止接收它,然后在屏幕上显示一些错误消息,例如Connection not available。 在我的情况下,它的某些第三方应用程序正在发送消息,并且它只是一种通信方式。 例如,我的应用程序发送了一些请求,而其他应用程序则继续发送响应。 因此,我需要监视该响应,并且某种程度上需要知道何时收到上一个响应。

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

我以前使用过Timer,它解决了这个问题,但作为新Timer出现了性能问题,每次接收到新消息时都会实例化新的TimerTask,从而创建了许多垃圾回收器无法快速回收的对象,从而导致outOfMemorry错误,使服务器无响应。 显然,这是一个错误的代码,这就是为什么我在这里寻求帮助。

请帮助我提供一些解决此问题的方法。

如果您使用最基本的工具进行处理,这将非常容易-有时遇到简单问题时,诸如线程池之类的增强工具只会分散琐碎的解决方案。

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

现在,您的方法所要做的就是每次运行时将(易失)时间戳更新为“现在”。 这里可能还有其他一些业务规则要实现,但这应该是一个很好的基础。

现在唯一的问题是如何通知听众。 如果这种情况很少发生,您可能可以在检查时间的同一线程上调用它们-但我认为您可以排除这种情况。 如果它发生的频率更高,但又不想/不需要它“嵌套”您的通知,则可以使第二个线程无处闲逛,除非在由观察者线程触发时通知客户端。

如果您需要“嵌套”通知(在原始通知返回之前通知侦听器),则需要一个线程池以使通知继续进行。

最后,我想如果您想在每10秒钟不捕获定时器,但又不想嵌套,则定时线程可以将“事件”推送到线程安全队列中,而“通知”线程可以将其退出并一次发送一个事件。

那应该涵盖所有可能性。

java.util.concurrent.Executors.newCachedThreadPool

创建一个线程池,该线程池根据需要创建新线程,但是将在先前构造的线程可用时重用它们。 这些池通常将提高执行许多短期异步任务的程序的性能。 如果可用,执行调用将重用以前构造的线程。 如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。 六十秒内未使用的线程将终止并从缓存中删除。 因此,保持空闲时间足够长的池不会消耗任何资源。 请注意,可以使用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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM