30 Mart 2021 Salı

Thread Sınıfı ve Uncaught Exception

Giriş 
Bence uncaught exceptionlar ile uğraşmak yerine, thread döngüsü içinde şöyle yapmak çok daha kolay.

Örnek
Şöyle yaparız
Thread t = new Thread(new Runnable(){
  @Override
  public void run(){
    while(...){
      try{
        ...
      }catch(InterruptedException ex){
        // you'll need to decide whether to ignore or not thread's interruption
        // This example is in case you decide not to ignore it
        ...
      }catch(Exception ex){
        logError(ex);
      } 
    } //while 
 } //run
});

t.start();
Neden Gerekir ?
Bir bir thread eğer unchecked exception'ı yakalamamışsa, Thread.UncaughtExceptionHandler arayüzünden kalıtan bir metod çalıştırılabilir.

Açıklaması şöyle
When a checked exception is thrown inside the run() method of a Thread object, we have to catch and treat it accordingly, because the run() method doesn’t accept a throws clause. But when an unchecked exception is thrown inside the run() method of a Thread object, the default behavior is to write the stack trace in the console (or log it inside the error log file) and exit the program.

However, with UncaughtExceptionHandler interface, Java provides us with a mechanism to catch and treat the unchecked exceptions thrown in a Thread object to avoid the program’s ending abruptly.
Açıklaması şöyle
So basically when a thread such as the main thread is about to terminate due to an uncaught exception the virtual machine will invoke the thread’s UncaughtExceptionHandler for a chance to perform some error handling like logging the exception to a file or uploading the log to the server before it gets killed.
İşleyiş sırası şöyle
1. Eğer Thread'e setUncaughtExceptionHandler() atanmışsa tetiklenir.
2. Eğer atanmamışsa, thread'in bağlı olduğu ThreadGroup'a setUncaughtExceptionHandler() atanmışsa tetiklenir. Açıklaması şöyle
Every Thread is a member of a ThreadGroup and if the terminated thread doesn’t have an explicitly set handler than it will forward to the thread group handler. If the thread group doesn’t hold any special handler for such cases, it will eventually call it’s default uncaught exception handler.
3. Eğer hiç biri yoksa default uncaught exception handler tetiklenir

setDefaultUncaughtExceptionHandler metodu
Örnek
Şöyle yaparız
Thread.setDefaultUncaughtExceptionHandler(...);
setUncaughtExceptionHandler metodu
Bu metod ile setDefaultUncaughtExceptionHandler() farklı çünkü diğeri static yani tüm thread'ler için geçerli. 
Örnek - thread'i tekrar çalıştırmak
Açıklaması şöyle
When an exception occurs and call reaches the uncaughtExceptionHandler, the state of the thread is Invalid to start again. So you need to create a new thread and start again.
Elimizde şöyle bir kod olsun. Dolayısıyla bu kod hatalı
thread.setUncaughtExceptionHandler((t, e) -> t.run());
Şöyle yaparız
static AtomicInteger counter = new AtomicInteger();

class MyExceptionHandler implements UncaughtExceptionHandler {
  @Override
  public void uncaughtException(Thread t, Throwable e) {
    
    if (counter.get() == 3) {
      System.out.println("Reached Max. retries, exiting");
    } else {
      counter.incrementAndGet();
      new Thread(new MyTask()).start();
    }
  }
}

class MyTask implements Runnable {
  @Override
  public void run() {
    Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHandler());
    ...
  }
}
Örnek
Thread dursun istiyorsak şöyle yaparız.
Thread thread = ...;

Thread.UncaughtExceptionHandler h = (t, exception) -> {
  t.interrupt();
};
thread.setUncaughtExceptionHandler(h);

Hiç yorum yok:

Yorum Gönder