我有一个Java应用程序,它处理来自通过串行端口到达的数据的数据流,并在Swing UI中显示摘要。
它工作正常,但是当我在某些线程(例如Swing事件调度线程)中在Eclipse中设置断点时,我在JVM爬行停止之前有一段有限的时间:传入的数据仍在处理中,并且某个系统队列,无论是数据队列还是事件队列,都会过满。
有什么方法可以在上游线程中检测到这一点,以便我的上游处理在调试期间开始丢弃数据?
如果我的程序显式使用队列,我可以在队列大小过高时丢弃数据。
但如果队列是“隐含的”,我不能这样做,例如它由我直接控制之外的其他软件管理。我可以想到两种可能性:
如果我正在使用SwingUtilities.invokeLater()
或其他调用SwingUtilities.invokeLater()的UI框架,如何检测Dispatch线程是否使用事件进行备份?
如果我正在使用ExecutorService.submit()
,如何检测执行程序的任务队列是否已备份?
更新:我想我已经通过包装我的ExecutorService解决了#2:
AbstractPipelineExecutor.java:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
/**
* pipeline executor
*/
abstract public class AbstractPipelineExecutor {
/**
* a pipeline scheduled item
*/
public interface Task extends Runnable
{
/**
* if item cannot be run, this is called instead
*/
public void denied();
}
final private ExecutorService executor;
public AbstractPipelineExecutor(ExecutorService executor)
{
this.executor = executor;
}
/**
* submit an item to be executed
* @param task pipeline item
*/
public Future<?> submit(final Task task)
{
Future<?> result = null;
if (this.executor.isShutdown())
{
task.denied();
}
else
{
try
{
onSubmit(task);
result = this.executor.submit(new Runnable() {
@Override public void run()
{
onBeginExecute(task);
try
{
task.run();
}
catch (RuntimeException e)
{
onExecutionException(task, e);
}
finally
{
onEndExecute(task);
}
}
});
}
catch (RejectedExecutionException e)
{
task.denied();
}
}
return result;
}
/**
* event handler: item is submitted
* @param task pipeline item
*/
abstract protected void onSubmit(Task task) throws RejectedExecutionException;
/**
* event handler: item execution is begun
* @param task pipeline item
*/
protected void onBeginExecute(Task task) {}
/**
* event handler: item throws a runtime exception
* @param task pipeline item
*/
protected void onExecutionException(Task task, RuntimeException e) {
throw(e);
}
/**
* event handler: item execution is ended
* @param task pipeline item
*/
protected void onEndExecute(Task task) {}
}
BoundedPipelineExecutor.java:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
public class BoundedPipelineExecutor extends AbstractPipelineExecutor {
public BoundedPipelineExecutor(ExecutorService executor, int bound) {
super(executor);
this.q = new ArrayBlockingQueue<Task>(bound);
}
final private ArrayBlockingQueue<Task> q;
@Override public void onSubmit(Task task)
{
if (!this.q.offer(task))
throw new RejectedExecutionException(task.toString());
}
@Override public void onBeginExecute(Task task)
{
this.q.remove();
}
}
答案 0 :(得分:1)
我建议他们不要直接从您的IO类中使用SwingUtilities.invokeLater,而是应该更新一个“摘要”,以便在更新UI时做出明智的决定。即使没有调试断点,您也不希望繁重的IO操作泛滥用户界面。
因此,创建一个接收和处理数据的类,并允许您的用户界面以适当的间隔轮询该信息。