Java – thread.join with “retry” mode

Using thread to view the sample code, I often encounter this retry mode

boolean retry = true;
while (retry) {
    try {
        myThread.join();
        retry = false;
    } catch (InterruptedException e) {
        // Nothing ...
    }
}

Join () should wait forever

If the current thread is interrupted before or during the connection and therefore receives an interruptedexception, does myThread actually join?

Is this some cutting residue turned into a pattern?

resolvent:

In the case of interruptedexception, another thread does not join (). Your thread. Join () should always wait or wait until the calling thread is interrupt () – ed

First, you need to consider whether an interruptedexception actually occurs. There are several possibilities for how to deal with it. You can:

>Swallow it. Warning do this only if you are sure that the interruptedexception will never happen. (are you sure? Really?) > set the interrupt flag again. If your code doesn't know how to handle it, that's what you do, But the thread is doing other things that may be interested in interruptedexception. > propagate it. If your current method doesn't know how to handle it, this is the best solution, but the caller may know. > handle it. When you receive interruptedexception, your current thread may just want to stop (by completing the run () method) . > wrap it in another exception. There are two variants

>If interruptedexception should not occur first and is obviously an error, you may want to wrap it in an assertion. > if your method is bound to a specific contract that does not allow interruptedexception, you may want to wrap it in another exception

In any case, I strongly recommend that you log () interruptedexception in some way. If you do not record it and it occurs, the behavior of the program may be difficult to understand if there is no log information about interruptedexception

Swallow it

Warning swallow it only if you are absolutely sure it is OK in your case. You are warned

public static void joinThread(final Thread thread) {
    while (true)
        try {
            thread.join();
            return;
        } catch (final InterruptedException e) {
            Logger.getGlobal().log(Level.ERROR, "Unexpected InterruptedException", e);
        }
}

As a variant, you can ignore it without retrying

public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.ERROR, "Unexpected InterruptedException", e);
    }
}

Set the interrupt flag again

If the thread is performing other operations, that's what you do. Your code doesn't know how to handle interruptedexception, and so do other code

public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.INFO, "Unexpected InterruptedException, resetting flag", e);
        Thread.currentThread().interrupt();
    }
}

But be careful! If other code really knows what to do, it's just a good idea. If other code performs the same operation and these things are circular (usually in the case of threads), you just need to convert the good blocking code into busy waiting garbage, Because the interrupt flag will never be cleared correctly. Although this solution is advertised as the best or real solution in many blog posts, it is nonsense as long as no code knows how to deal with interruptedexception and actually keeps the flag cleared instead of resetting it

Spread it

If the method itself does not know how to handle it, this is the best solution, but the caller may know

public static void joinThread(final Thread thread) throws InterruptedException {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.FINE, "Got InterruptedException, propagating it to the caller", e);
        throw e;
    }
}

If the caller does something good, you can delete unnecessary parts, such as recording and re throwing

Deal with it

If the method itself knows that it must do something when interrupted, it can simply catch exceptions and do anything expected

public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.FINE, "Got InterruptedException, handling it", e);
        // ...whatever...
    }
}

Pack it

If an exception should not occur, because the application does not support interrupts, and should not call thread. Interrupt() or ThreadGroup. Interrupt() first, it is possible to convert the exception to assertionerror. There are two possibilities

// Only throws AssertionError if assertions are enabled.
public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.ERROR, "Unexpected InterruptedException", e);
        assert false : e;
    }
}

// Always throws AssertionError.
public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.FATAL, "Unexpected InterruptedException", e);
        throw new AssertionError(e, "Unexpected Thread interruption.");
    }
}

If you want to propagate an interruptedexception, but the caller does not support the exception and cannot change it, you can wrap it in a supported exception. Whether this works and is a good idea depends largely on the caller

public static void joinThread(final Thread thread) {
    try {
        thread.join();
    } catch (final InterruptedException e) {
        Logger.getGlobal().log(Level.ERROR, "Unexpected InterruptedException", e);
        throw new SomeException(e, "Unexpected Thread interruption.");
    }
}

Final notes

There are some discussions that swallowing is always bad. This is not true. If you have 100 lines of code and do thread. Sleep() somewhere for some reason, swallowing is usually good. As always, it depends. Finally, the semantics of thread. Interrupt() is not very different from SIGHUP, and SIGHUP is usually ignored

There is also some discussion about whether it is a good idea to convert it to assertionerror. Assertionerror is an unchecked throwable, not even an exception, which means that the compiler does not force the code to process it, and most code will not write to process it - this is intentional, because by using assertionerror, we say that the error here is so unexpected, So that the code doesn't know how to handle it, so it wants to stop. Whether the assertionerror terminates the VM depends on the thread to be deleted because the assertionerror is thrown to the uncaughtexceptionhandlers of the affected thread

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>