Domanda

Ehi, sto scrivendo un'applicazione di rete, in cui ho letto i pacchetti di qualche formato binario personalizzato. E sto iniziando un thread in background per aspettare i dati in ingresso. Il problema è, che il compilatore non mi permette di mettere tutte le eccezioni (controllato) codice di lancio in run(). Dice:

run() in (...).Listener cannot implement run() in java.lang.Runnable; overridden method does not throw java.io.IOException

Voglio l'eccezione di uccidere il filo, e lascia che sia catturato da qualche parte nel thread genitore. Questo è possibile per raggiungere o devo per gestire ogni eccezione all'interno il filo?

È stato utile?

Soluzione

Avvertenza: questo non può soddisfare le vostre esigenze, se si deve utilizzare il meccanismo di eccezione

.

Se ho capito bene, non è effettivamente bisogno l'eccezione da controllare (hai accettato la risposta che suggerisce un'eccezione unchecked) quindi sarebbe un modello semplice ascoltatore essere più appropriato?

L'ascoltatore potrebbe vivere nel thread genitore, e quando hai preso l'eccezione controllata nel thread bambino, si potrebbe semplicemente avvisare l'ascoltatore.

Questo significa che avete un modo di esporre che questo accadrà (attraverso metodi pubblici), e sarà in grado di trasmettere più informazioni di un'eccezione permetterà. Ma significa ci sarà un accoppiamento (anche se molto sciolto) tra il genitore e il thread figlio. Sarebbe dipenderà nella vostra situazione specifica se questo avrebbe un vantaggio rispetto avvolgendo l'eccezione controllata con uno incontrollato.

Ecco un semplice esempio (codice preso in prestito da un'altra risposta):

public class ThingRunnable implements Runnable {
    private SomeListenerType listener;
    // assign listener somewhere

    public void run() {
        try {
            while(iHaveMorePackets()) { 
                doStuffWithPacket();
            }
        } catch(Exception e) {
            listener.notifyThatDarnedExceptionHappened(...);
        }
    }
 }

L'accoppiamento viene da un oggetto nel thread genitore dover essere di tipo SomeListenerType.

Altri suggerimenti

Per essere in grado di inviare l'eccezione al thread genitore, si può mettere il thread in background in un Callable (permette lancio anche controllato eccezioni) che poi passa al presentare metodo di alcuni esecutore . Il metodo di invio restituisce un Future che è quindi possibile utilizzare per ottenere l'eccezione (la sua ottenere metodo genera un ExecutionException che contiene l'eccezione originale).

Questa risposta si basa su Esko Luontola uno ma fornisce un esempio di lavoro.

A differenza del metodo run () dell'interfaccia Runnable il metodo call () di richiamabile consente di gettare alcune eccezioni. Ecco un esempio di implementazione:

public class MyTask implements Callable<Integer> {

    private int numerator;
    private int denominator;

    public MyTask(int n, int d) {
        this.numerator = n;
        this.denominator = d;
    }

    @Override
    // The call method may throw an exception
    public Integer call() throws Exception {
        Thread.sleep(1000);
        if (denominator == 0) {
            throw new Exception("cannot devide by zero");
        } else {
            return numerator / denominator;
        }
    }

}

esecutore fornisce un meccanismo per eseguire una richiamabile all'interno di un filo e di gestire qualsiasi tipo di eccezioni:

public class Main {

    public static void main(String[] args) {

        // Build a task and an executor
        MyTask task = new MyTask(2, 0);
        ExecutorService threadExecutor = Executors.newSingleThreadExecutor();

        try {
            // Start task on another thread
            Future<Integer> futureResult = threadExecutor.submit(task);

            // While task is running you can do asynchronous operations
            System.out.println("Something that doesn't need the tasks result");

            // Now wait until the result is available
            int result = futureResult.get();
            System.out.println("The result is " + result);
        } catch (ExecutionException e) {
            // Handle the exception thrown by the child thread
            if (e.getMessage().contains("cannot devide by zero"))
                System.out.println("error in child thread caused by zero division");
        } catch (InterruptedException e) {
            // This exception is thrown if the child thread is interrupted.
            e.printStackTrace();
        }
    }
}

Quello che faccio è quello di catturare l'eccezione nel thread e conservarla come una variabile membro della Runnable. Questa eccezione viene poi esposta tramite un getter sul Runnable. Ho quindi eseguire la scansione tutti i fili dal padre per vedere se avevano eccezioni, e intraprendere l'azione appropriata.

il thread non può generare l'eccezione a qualsiasi altro thread (né per il thread principale). e non è possibile effettuare il metodo run ereditato () gettare qualsiasi eccezioni controllate dal momento che si può solo buttare meno il codice ereditato, non di più.

Se davvero non si può fare qualcosa di utile quando l'eccezione è sollevata si può avvolgere l'eccezione verificata in un RuntimeException.

try {
    // stuff
} catch (CheckedException yourCheckedException) {
    throw new RuntimeException("Something to explain what is happening", yourCheckedException);
}

Se il codice del vostro filetto gettare un RuntimeExpection, è non ha bisogno di aggiungere run () un tiro di eccezione.

Ma utilizzare questa soluzione solo quando appropriato, perché questo può essere un cattivo pratice: http://java.sun.com/docs/books/ tutorial / essenziali / eccezioni / runtime.html

Qualsiasi RuntimeException o eccezione incontrollato può aiutare. Forse avrete bisogno di creare il proprio RuntimeException

Partendo dal presupposto che il codice è in una sorta di loop, avrebbe scritto:

public class ThingRunnable implements Runnable {
  public void run() {
    try {
      while(iHaveMorePackets()) { 
        doStuffWithPacket()
      }
    } catch(Exception e) {
      System.out.println("Runnable terminating with exception" + e );
    }
  }
}

L'eccezione verrà automaticamente uscire dal loop, e alla fine del metodo run (), il filo si fermerà.

avvolgendo l'eccezione all'interno di un RuntimeException sembra fare il trucco.

someMethod() throws IOException
{
    try
    {
        new Thread(() ->
        {
            try
            {
                throw new IOException("a checked exception thrown from within a running thread");
            }
            catch(IOException ex)
            {
                throw new RuntimeException("a wrapper exception", ex); // wrap the checked exception inside an unchecked exception and throw it
            }
        }).start();
    }
    catch(RuntimeException ex) // catch the wrapped exception sent from within the thread
    {
        if(ex.getCause() instanceof IOException)
            throw ex.getCause; // unwrap the checked exception using getCause method and use it however you need
        else
            throw ex;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top