请花点时间阅读以下内容。我们将非常感谢您的帮助
我有一个场景需要监控一些实时活动。比如说一个方法在毫秒内实时调用。我必须监视好像首次调用该方法以及何时最后调用该方法。
所以,在最后一次击中该方法后,我需要等待一段时间,比如10秒,看看它是否在那段时间内没有再次调用。如果没有调用那么我需要运行一些代码。
我想使用 ExecuterService 并使用 newCachedThreadPool()。但我对如何实现这一点很困惑。
如果您不确定我在说什么,请举一些例子说,当有网络故障时,你接收到心跳并突然停止接收它,然后你在屏幕上显示一些错误消息,例如:连接不可用。在我的情况下,它的一些第三方应用程序正在发送一些消息,它只是单向通信。就像,我的应用程序发送了一些请求,其他应用程序继续发送响应。因此,我需要监控该响应,并以某种方式需要知道我何时收到最后一个响应。
我的方法 - 我想在每次调用该方法时执行一个任务,该方法将等待10秒并且在10秒内,如果再次调用该方法,它将以某种方式取消当前任务并将创建另一个任务(或重用,如果可能),这将再次运行10秒。这将继续发生,直到收到最后一条消息(当方法最后被调用时),然后一旦10秒延迟结束,任务将被执行,一些代码将运行以在UI上显示错误消息。
我之前使用过Timer,它解决了这个问题但创建了一个性能问题,因为新的Timer会在每次收到新消息时实例化一个新的TimerTask,因此会产生很多垃圾收集器无法快速回收的对象,因此导致outOfMemorry错误并使服务器无响应。显然这是一个糟糕的代码,这就是我在这里求助的原因。
请帮我解决这个问题。
答案 0 :(得分:1)
如果您使用最基本的工具来处理它,这很容易 - 有时候遇到简单的问题,线程池之类的增强工具会分散注意力。
假设您有一个简单的线程(Runnable)。该线程检查时间戳以查看该时间戳是否为10秒。如果是你通知你的听众,如果没有,你会延迟几毫安并再次检查。
现在你所要做的就是每次运行时将(volatile)时间戳更新为“now”。可能会有一些其他业务规则在这里实施,但它应该是一个很好的基础。
现在唯一的问题是你如何通知你的听众。如果这种情况很少发生,你可以在你正在检查时间的同一个线程上调用它们 - 但我认为你已经排除了这一点。如果它经常发生但您不希望/需要它“嵌套”您的通知,您可以暂停第二个线程,除非在您的观察者线程触发时通知客户端。
如果您需要“嵌套”通知(在原始通知返回之前通知侦听器),那么您需要一个线程池来通知您的通知。
最后我想如果你想抓住你的计时器没有被调用10秒但你不想嵌套,你的计时线程可以将“事件”推送到线程安全队列而你的“通知”线程可以将它们拉下来并一次发送一个事件。
这应该涵盖所有可能性。
答案 1 :(得分:0)
您可以使用ScheduledExecutorService。
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
答案 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();