简体   繁体   English

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

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

Please take time to read below. 请花时间阅读以下内容。 Your help will be highly appreciated 非常感谢您的帮助

I have a scenario where I need to monitor some realtime activity. 我有一个需要监视一些实时活动的场景。 Say for example a method is getting called in realtime within milli seconds. 假设某个方法在毫秒内被实时调用。 I have to monitor as if when the method was first called and when the method was called last. 我必须监视好像第一次调用该方法以及何时最后调用该方法。

So, after that method is hit last I need to wait for sometime say 10 seconds and see if it doesn't called again within that time. 因此,在该方法被最后击中之后,我需要等待一段时间,例如10秒钟,然后查看在该时间内是否没有再次调用它。 If its not called then I need to run some code. 如果未调用,则需要运行一些代码。

I want to use ExecuterService and use newCachedThreadPool() . 我想使用ExecuterService并使用newCachedThreadPool() But I am confused on how to implement this. 但是我对如何实现这一点感到困惑。

If you are not sure what I am talking about, take some example of say when there is some network breakdown and u where receiving heartbeats and suddenly u stopped receiving it then you show some error message on screen for eg Connection not available. 如果您不确定我在说什么,请举个例子,例如,当网络出现故障时,并且u在接收到心跳信号时突然突然停止接收它,然后在屏幕上显示一些错误消息,例如Connection not available。 In my case its some third party application which is sending some message and its just one way communication. 在我的情况下,它的某些第三方应用程序正在发送消息,并且它只是一种通信方式。 Like, my application sent some request and other application keep on sending responses. 例如,我的应用程序发送了一些请求,而其他应用程序则继续发送响应。 So, I need to monitor that response and somehow need to know when I received the last response. 因此,我需要监视该响应,并且某种程度上需要知道何时收到上一个响应。

My approach - I thought of executing a task each time that method is called which will wait for 10 seconds and within 10 seconds, if that method got called again, it will somehow cancel the current task and will create another task (or reuse if possible) which will again run for 10 seconds. 我的方法 -我想到了每次调用该方法都会执行一个任务,该方法将等待10秒,并且在10秒之内,如果再次调用该方法,它将以某种方式取消当前任务并创建另一个任务(或在可能的情况下重用) ),它将再次运行10秒钟。 This will keep on happening until the last message received (when the method got called last) and after that once 10 sec delay is over, the task will be executed and some code will run to show error message on the UI. 这将一直持续到收到最后一条消息为止(该方法最后一次调用时),并且在此之后10秒钟的延迟结束后,将执行任务并运行一些代码以在UI上显示错误消息。

I have used Timer earlier, which solved this problem but created a performance issue as new Timer which a new TimerTask is instantiated every time a new message is received hence creating a hell lot of objects which garbage collector could not reclaim that fast, thus resulting in outOfMemorry Error and making Server non responsive. 我以前使用过Timer,它解决了这个问题,但作为新Timer出现了性能问题,每次接收到新消息时都会实例化新的TimerTask,从而创建了许多垃圾回收器无法快速回收的对象,从而导致outOfMemorry错误,使服务器无响应。 Obviously it was a bad code that's why I am here for help. 显然,这是一个错误的代码,这就是为什么我在这里寻求帮助。

Please help me in giving some approach to solve this problem. 请帮助我提供一些解决此问题的方法。

This is quite easy if you approach it with the most basic of tools--sometimes with simple problems the enhanced tools like thread pools just distract from a trivial solution. 如果您使用最基本的工具进行处理,这将非常容易-有时遇到简单问题时,诸如线程池之类的增强工具只会分散琐碎的解决方案。

Let's say you have a simple thread (Runnable). 假设您有一个简单的线程(Runnable)。 That thread checks a time stamp to see if that time stamp is 10 seconds old. 该线程检查时间戳以查看该时间戳是否为10秒。 If it is you notify your listener, if not you delay a few millis and check again. 如果是,则通知您的听众;否则,请延迟几毫秒,然后再次检查。

Now all your method has to do is update the (volatile) time stamp to "now" every time it runs. 现在,您的方法所要做的就是每次运行时将(易失)时间戳更新为“现在”。 There may be some other business rules to implement here but it should be a good foundation. 这里可能还有其他一些业务规则要实现,但这应该是一个很好的基础。

The only issue now is how you notify your listeners. 现在唯一的问题是如何通知听众。 If this happens rarely you can probably call them on the same thread you are checking the time with--but I think you ruled that out. 如果这种情况很少发生,您可能可以在检查时间的同一线程上调用它们-但我认为您可以排除这种情况。 If it happens more often but you don't want/need it to "nest" your notifications, you can have a second thread hanging around with no purpose except to notify the client when triggered by your watcher thread. 如果它发生的频率更高,但又不想/不需要它“嵌套”您的通知,则可以使第二个线程无处闲逛,除非在由观察者线程触发时通知客户端。

If you need to "nest" notifications (notify the listener before the original notification has returned) then you need a thread pool for your notifications to go out on. 如果您需要“嵌套”通知(在原始通知返回之前通知侦听器),则需要一个线程池以使通知继续进行。

Finally I suppose if you want to catch EVERY time your timer isn't called for 10 seconds but you don't want to nest, your timing thread could push "events" onto a threadsafe queue and your "Notification" thread could pull them off and send the events one at a time. 最后,我想如果您想在每10秒钟不捕获定时器,但又不想嵌套,则定时线程可以将“事件”推送到线程安全队列中,而“通知”线程可以将其退出并一次发送一个事件。

That should cover all the possibilities. 那应该涵盖所有可能性。

java.util.concurrent.Executors.newCachedThreadPool : java.util.concurrent.Executors.newCachedThreadPool

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. 创建一个线程池,该线程池根据需要创建新线程,但是将在先前构造的线程可用时重用它们。 These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. 这些池通常将提高执行许多短期异步任务的程序的性能。 Calls to execute will reuse previously constructed threads if available. 如果可用,执行调用将重用以前构造的线程。 If no existing thread is available, a new thread will be created and added to the pool. 如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。 Threads that have not been used for sixty seconds are terminated and removed from the cache. 六十秒内未使用的线程将终止并从缓存中删除。 Thus, a pool that remains idle for long enough will not consume any resources. 因此,保持空闲时间足够长的池不会消耗任何资源。 Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors 请注意,可以使用ThreadPoolExecutor构造函数创建具有相似属性但细节不同(例如,超时参数)的池

As you have many short-lived tasks, cached thread pool is best option. 由于您有许多短期任务,因此缓存线程池是最佳选择。

Short example: 简短示例:

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;
    }
}

To run WorkerThread use : 要运行WorkerThread使用:

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

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

To stop WorkerThread use: 要停止使用WorkerThread

executor.shutdown();

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

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