Is it acceptable in Java to use thread #stop() to kill a running thread?

Unfortunately, you cannot specify a timeout when using regular expressions for strings in Java Therefore, if you don't strictly control which patterns apply to which input, you may end up with CPU consuming threads and endless attempts to combine (less well-designed) patterns with (malicious?) Input matches

I know why thread #stop() is deprecated (see http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html )They focus on objects that may be corrupted under ThreadDeath exceptions, and then pollute the running JVM environment and may lead to subtle errors

My question for someone who has a deeper understanding of the JVM's work is: if the thread that needs to be stopped does not have any (obvious) monitors or references to objects used by the rest of the program, can thread#stop() be used?

I created a fairly defensive solution that can handle regular expressions that match timeouts I will be happy with any comments or comments, especially despite my efforts to avoid them, the problems that this approach may cause

thank you!

import java.util.concurrent.Callable;

public class SafeRegularExpressionMatcher {

    // demonstrates behavior for regular expression running into catastrophic backtracking for given input
    public static void main(String[] args) {
        SafeRegularExpressionMatcher matcher = new SafeRegularExpressionMatcher(
                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","(x+x+)+y",2000);
        System.out.println(matcher.matches());
    }

    final String stringToMatch;

    final String regularExpression;

    final int timeoutMillis;

    public SafeRegularExpressionMatcher(String stringToMatch,String regularExpression,int timeoutMillis) {
        this.stringToMatch = stringToMatch;
        this.regularExpression = regularExpression;
        this.timeoutMillis = timeoutMillis;
    }

    public Boolean matches() {
        CallableThread<Boolean> thread = createSafeRegularExpressionMatchingThread();
        Boolean result = tryToGetResultFromThreadWithTimeout(thread);
        return result;
    }

    private CallableThread<Boolean> createSafeRegularExpressionMatchingThread() {
        final String stringToMatchForUseInThread = new String(stringToMatch);
        final String regularExpressionForUseInThread = new String(regularExpression);
        Callable<Boolean> callable = createRegularExpressionMatchingCallable(stringToMatchForUseInThread,regularExpressionForUseInThread);
        CallableThread<Boolean> thread = new CallableThread<Boolean>(callable);
        return thread;
    }

    private Callable<Boolean> createRegularExpressionMatchingCallable(final String stringToMatchForUseInThread,final String regularExpressionForUseInThread) {
        Callable<Boolean> callable = new Callable<Boolean>() {
            public Boolean call() throws Exception {
                return Boolean.valueOf(stringToMatchForUseInThread.matches(regularExpressionForUseInThread));
            }
        };
        return callable;
    }

    private Boolean tryToGetResultFromThreadWithTimeout(CallableThread<Boolean> thread) {
        startThreadAndApplyTimeout(thread);
        Boolean result = processThreadResult(thread);
        return result;
    }

    private void startThreadAndApplyTimeout(CallableThread<Boolean> thread) {
        thread.start();
        try {
            thread.join(timeoutMillis);
        } catch (InterruptedException e) {
            throwRuntimeException("Interrupt",e);
        }
    }

    private Boolean processThreadResult(CallableThread<Boolean> thread) {
        Boolean result = null;
        if (thread.isAlive()) {
            killThread(thread); // do not use anything from the thread anymore,objects may be damaged!
            throwRuntimeException("Timeout",null);
        } else {
            Exception exceptionOccurredInThread = thread.getException();
            if (exceptionOccurredInThread != null) {
                throwRuntimeException("Exception",exceptionOccurredInThread);
            } else {
                result = thread.getResult();
            }
        }
        return result;
    }

    private void throwRuntimeException(String situation,Exception e) {
        throw new RuntimeException(situation + " occured while applying pattern /" + regularExpression + "/ to input '"
                + stringToMatch + " after " + timeoutMillis + "ms!",e);
    }

    /**
     * This method uses {@link Thread#stop()} to kill a thread that is running wild. Although it is ackNowledged that
     * {@link Thread#stop()} is inherently unsafe,the assumption is that the thread to kill does not hold any monitors on or
     * even references to objects referenced by the rest of the JVM,so it is acceptable to do this.
     * 
     * After calling this method nothing from the thread should be used anymore!
     * 
     * @param thread Thread to stop
     */
    @SuppressWarnings("deprecation")
    private static void killThread(CallableThread<Boolean> thread) {
        thread.stop();
    }

    private static class CallableThread<V> extends Thread {

        private final Callable<V> callable;

        private V result = null;

        private Exception exception = null;

        public CallableThread(Callable<V> callable) {
            this.callable = callable;
        }

        @Override
        public void run() {
            try {
                V result = compute();
                setResult(result);
            } catch (Exception e) {
                exception = e;
            } catch (ThreadDeath e) {
                cleanup();
            }
        }

        private V compute() throws Exception {
            return callable.call();
        }

        private synchronized void cleanup() {
            result = null;
        }

        private synchronized void setResult(V result) {
            this.result = result;
        }

        public synchronized V getResult() {
            return result;
        }

        public synchronized Exception getException() {
            return exception;
        }

    }

}

Edit:

Thank dawce for pointing out that I have been able to solve my original problem without additional threads I released the code there Thank all those who replied

Solution

If you determine that it is the only available solution, you can use thread stop(). You may need to close and restart the application to ensure that it is in good condition

Note: a thread can catch and ignore ThreadDeath, so it is not guaranteed to stop all threads

Another way to stop a thread is to run it in a different process This can be killed as needed This can still make resources unstable (such as locking files), but it is unlikely and easier to control

Of course, the best solution is to fix the code so that it doesn't do this first, but respects thread interrupt().

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
分享
二维码
< <上一篇
下一篇>>