简体   繁体   中英

Catch a Runtime Exception thrown from ActionListener in a Waiting Runnable

I am working on a Uni project to implement a Texas Hold'em poker game. I have been working on a way to to halt the game while waiting for user input (from GUI) if no input is received then the player will be folded. My initial code just called sleep() on the game thread and then notify() from the controller. The problem I ran into with this method was I had no way to tell if the controller had notified or the that sleep had ended. To try and flag this I had the controller throw a RuntimeException but have had alot of trouble trying to catch this exception at the game thread.

Here is my minimum viable example:

GUI.java

import java.awt.GraphicsConfiguration;
import java.awt.HeadlessException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GUI extends JFrame
{
    private JButton jb;
    private JPanel jp;
    private WaitTest wt;

    public GUI(WaitTest wt) throws HeadlessException
    {
        // TODO Auto-generated constructor stub
        this.wt = wt;
        jp = new JPanel();
        jb = new JButton("Throw Runtime");
        jp.add(jb);
        jb.addActionListener(new TestController(wt));
        this.add(jp);
        pack();
        this.setVisible(true);
    }

    public GUI(GraphicsConfiguration gc)
    {
        super(gc);
        // TODO Auto-generated constructor stub
    }

    public GUI(String title) throws HeadlessException
    {
        super(title);
        // TODO Auto-generated constructor stub
    }

    public GUI(String title, GraphicsConfiguration gc)
    {
        super(title, gc);
        // TODO Auto-generated constructor stub
    }

}

TestController.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TestController implements ActionListener
{
    private WaitTest wt;

    public TestController(WaitTest wt)
    {
        this.wt = wt;
    }

    @Override 
    public void actionPerformed(ActionEvent e){
        // TODO Auto-generated method stub
        System.out.println("Controller throws runtime");
        synchronized(wt.getT())
        {
            throw new RuntimeException("Runtime flying");
        }
    }
}

WaitTest.java

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class WaitTest implements Runnable
{
    private Thread t;

    public WaitTest()
    {
        // TODO Auto-generated constructor stub
        this.t = new Thread();
    }

    public Thread getT()
    {
        return t;
    }

    public void run()
    {
        try
        {
            synchronized (this)
            {
                Thread.sleep(3000);
                System.out.println("Player folded");
            }
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block

            System.out.println("Caught ");
        }

        System.out.println("interupt not received");

    }

    public void test() throws InterruptedException
    {
        // TODO Auto-generated method stub
        ExecutorService executor = Executors.newSingleThreadExecutor();
        synchronized (t)
        {
            Future<?> future = executor.submit(this);
            try
            {
                future.get();
            }
            catch (ExecutionException e)
            {
                System.out.println("hooray!! runtime caught");
                t.notify();
                return;
            }
            catch (Exception ex)
            {
                System.out.println("Runtime caught");
                t.notify();
                return;

            }
        }
    }

}

Driver.java

public class driver
{

    public driver()
    {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) throws InterruptedException
    {
        // TODO Auto-generated method stub
        WaitTest wt = new WaitTest();
        GUI gui = new GUI(wt);
        wt.test();
        gui.repaint();

    }
}

The runtime Exception is never caught is there a simple way to catch this? or is there a better way to stop the game loop and wait for input? This is my first attempt at thread control/concurrency so I am probably overlooking something simple

I was able to fix this by converting WaitTest to extend TimerTask (which implements Runnable) and changing Thread() to Timer() .

Then in the controller instead of needing to throw a Runtime Exception I just called cancel() on the timer

This is much cleaner for my purposes the mucking about with Executors and exceptions

WaitTest.java now looks like this:

import java.util.Timer;
import java.util.TimerTask;

public class WaitTest extends TimerTask
{
    private Timer t;

    public WaitTest()
    {
        // TODO Auto-generated constructor stub
        this.t = new Timer(true);
    }
    public void run()
    {
        System.out.println("Player folded");

    }

    public void test()
    {
        // Schedule task for 5 sec time unless the 
        // controller cancels
        t.schedule(this, 5000);

    }

    public Timer getT()
    {
        return t;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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