Java: detecting a deadlock in implicit queues when debugging a breakpoint

I have a Java application that processes a stream of data from data coming in through a serial port and displays a summary in the Swing user interface.

It works fine, but when I set breakpoints in Eclipse in specific threads (like a Swing event dispatch thread), I have a limited amount of time before the JVM scans to a stop: incoming data is still being processed and some system queue, whether The data queue or event queue is full.

Is there any way to detect this in upstream threads so that my thread processing starts discarding data during debugging?

If my program explicitly uses the queue, I can just throw out the data when the queue size becomes too high.

But I cannot do this if the queue is "implicit", for example. it was controlled by some other software that was beyond my direct control. I can imagine two possibilities:

  • If I use SwingUtilities.invokeLater()either another user interface structure that calls SwingUtilities.invokeLater (), how can I detect a backup of the event stream with events?

  • If I use ExecutorService.submit(), how can I determine if there will be a backup of the executor's task queue?


update: I think I decided # 2 by wrapping my ExecutorService:

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();
    }
}
+3
source share
1

, SwingUtilities.invokeLater -, "", . , - .

, , , .

+1

Source: https://habr.com/ru/post/1783420/


All Articles