简体   繁体   English

捕获异常后重新启动线程

[英]restart a thread after exception is caught

I am reading a UDP feed and I want the thread to attempt to restart if their is a failure. 我正在读取UDP提要,并且如果线程失败,我希望线程尝试重新启动。 I think I have written my class correctly but would like someone to look over and see if there is something missing or I have written something that won't get the job done. 我想我已经正确地写了我的课,但想找人看一下,看看是否有遗漏的东西,或者我写的东西无法完成工作。 In my catch clause I attempt to restart the thread every 6 seconds for 10 attempts. 在我的catch子句中,我尝试每6秒重新启动一次线程,进行10次尝试。 Is this a good solution, will it work? 这是一个好的解决方案,它会起作用吗?

class UDPReader extends Thread
{
    private Thread t;
    private final String ip, socket, queue, threadName;
    private String ErrorMessage;
    private final JTextArea screen;

    UDPReader(String ip, String socket, String queue, String threadName, JTextArea screen) {
        this.ip = ip;
        this.socket = socket;
        this.queue = queue;
        this.threadName = threadName;
        this.screen = screen;
    }

    public void run()
    {
        try {
            byte[] i = null;
            ipaddrConnection ipaddr = new ipaddrConnection(ip, socket);
            parseUDP p = new parseUDP();

            screen.append("Thread " + threadName + " running\n");
            while(true)
            {
                i = ipaddr.getPacket();
                p.parseUDP(i); 
                //Thread.sleep(0);
            }
        } 
        catch (IOException ex) {
            Logger.getLogger(MarketDataReader.class.getName()).log(Level.SEVERE, null, ex);
            ErrorMessage = "Thread " + threadName + " has failed, Attempting to Restart";
            screen.append("Thread " + threadName + " has failed, Attempting to Restart\n");
            Email email = new Email(ErrorMessage,"WARNING Market Data Reader Failure");

            for(int i = 0; i < 10 && t.isAlive() == false; i++)
            {
                try {
                    start();
                    Thread.sleep(6000);
                } catch (InterruptedException ex1) {
                    Logger.getLogger(UDPReader.class.getName()).log(Level.SEVERE, null, ex1);
                    ErrorMessage = "Thread " + threadName + " has failed, Contact System Administraitor";
                    screen.append("Thread " + threadName + " has failed, Contact System Administraitor\n");
                    email = new Email(ErrorMessage,"WARNING Market Data Reader Failure");
                }
            }
        }
    }

    public void start() 
    {
        if (t == null)
      {
         t = new Thread (this, threadName);
         t.start ();
      }
    }
}

I do not know the logic behind your thread in detail but I would make some suggestions on the design of your code. 我不知道您线程的详细逻辑,但我会对您的代码设计提出一些建议。

  1. It is not clear why inside a class derived from thread you have another thread t. 目前尚不清楚为什么在从线程派生的类中有另一个线程t。

  2. There is no need to derive from Thread (and I believe it is generally a bad practice). 不需要从Thread派生(我认为这通常是一种不好的做法)。 It is common to rather implement Runnable interface and then construct a new thread using it. 通常,宁可实现Runnable接口,然后使用该接口构造一个新线程。

.

class UDPReader implements Runnable {
...
}

and then instantiate a thread like this: 然后实例化这样的线程:

Thread t = new Thread(new UDPReader());
  1. As a rule, if a thread fails, it terminates... It does not look good that a failed thread "recreates" itself. 通常,如果线程失败,则线程终止...失败的线程自身“重新创建”看起来并不好。 The better solution would be to provide a Thread.UncaughtExceptionHandler and in the code that creates your thread analyze failing conditions and restart you thread if needed. 更好的解决方案是提供Thread.UncaughtExceptionHandler并在创建线程的代码中分析失败情况并在需要时重新启动线程。

In general, not to mess up, in concurrent programming you have to clearly distinguish the logic of a thread and external logic that manages this thread (its start/interruption/termination). 通常,为了避免混乱,在并发编程中,您必须清楚地区分线程的逻辑和管理该线程的外部逻辑(其启动/中断/终止)。 I think, this is what you did not do in your code. 我认为,这是您在代码中未执行的操作。

I'd say that it is a very bad design to restart a thread from inside of the same thread. 我想说,从同一线程内部重新启动线程是一个非常糟糕的设计。

If you need a 'supervisor' thread then you should most likely create another 'supervisor' thread that would create and start the 'worker' thread whenever it finds out that 'worker' thread is down. 如果您需要一个“主管”线程,那么您很可能应该创建另一个“主管”线程,该线程将在发现“工人”线程关闭时创建并启动“工人”线程。

One thing you should be aware of is that when you catch an exception in Java, the program (or thread) does not terminate unless you tell it too. 您应该意识到的一件事是,当您在Java中捕获异常时,程序(或线程)不会终止,除非您也告诉了它。

Therefore, if you caught your exception exactly at the command that caused it to happen - inside the loop - you would not need to run another thread. 因此,如果您恰好在导致异常发生的命令(循环内)中捕获了异常,则无需运行其他线程。 Your thread is alive and will continue to loop. 您的线程仍然存在,并且将继续循环。 All you need to do - inside the catch block - is fix things up so that the next loop can continue as usual - close and reopen streams, clear partially filled data structures, stuff like that. 您需要做的-在catch块内-修复问题,以便下一个循环可以照常继续-关闭并重新打开流,清除部分填充的数据结构,诸如此类。

Of course, if further, unrecoverable exceptions happen, you should indeed stop your thread. 当然,如果发生进一步的不可恢复的异常,则确实应该停止线程。

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

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