How to timeout a thread

后端 未结 17 1597
时光说笑
时光说笑 2020-11-22 01:01

I want to run a thread for some fixed amount of time. If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How

17条回答
  •  佛祖请我去吃肉
    2020-11-22 01:30

    I post you a piece of code which show a way how to solve the problem. As exemple I'm reading a file. You could use this method for another operation, but you need to implements the kill() method so that the main operation will be interrupted.

    hope it helps

    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * Main class
     * 
     * @author el
     * 
     */
    public class Main {
        /**
         * Thread which perform the task which should be timed out.
         * 
         * @author el
         * 
         */
        public static class MainThread extends Thread {
            /**
             * For example reading a file. File to read.
             */
            final private File fileToRead;
            /**
             * InputStream from the file.
             */
            final private InputStream myInputStream;
            /**
             * Thread for timeout.
             */
            final private TimeOutThread timeOutThread;
    
            /**
             * true if the thread has not ended.
             */
            boolean isRunning = true;
    
            /**
             * true if all tasks where done.
             */
            boolean everythingDone = false;
    
            /**
             * if every thing could not be done, an {@link Exception} may have
             * Happens.
             */
            Throwable endedWithException = null;
    
            /**
             * Constructor.
             * 
             * @param file
             * @throws FileNotFoundException
             */
            MainThread(File file) throws FileNotFoundException {
                setDaemon(false);
                fileToRead = file;
                // open the file stream.
                myInputStream = new FileInputStream(fileToRead);
                // Instantiate the timeout thread.
                timeOutThread = new TimeOutThread(10000, this);
            }
    
            /**
             * Used by the {@link TimeOutThread}.
             */
            public void kill() {
                if (isRunning) {
                    isRunning = false;
                    if (myInputStream != null) {
                        try {
                            // close the stream, it may be the problem.
                            myInputStream.close();
                        } catch (IOException e) {
                            // Not interesting
                            System.out.println(e.toString());
                        }
                    }
                    synchronized (this) {
                        notify();
                    }
                }
            }
    
            /**
             * The task which should be timed out.
             */
            @Override
            public void run() {
                timeOutThread.start();
                int bytes = 0;
                try {
                    // do something
                    while (myInputStream.read() >= 0) {
                        // may block the thread.
                        myInputStream.read();
                        bytes++;
                        // simulate a slow stream.
                        synchronized (this) {
                            wait(10);
                        }
                    }
                    everythingDone = true;
                } catch (IOException e) {
                    endedWithException = e;
                } catch (InterruptedException e) {
                    endedWithException = e;
                } finally {
                    timeOutThread.kill();
                    System.out.println("-->read " + bytes + " bytes.");
                    isRunning = false;
                    synchronized (this) {
                        notifyAll();
                    }
                }
            }
        }
    
        /**
         * Timeout Thread. Kill the main task if necessary.
         * 
         * @author el
         * 
         */
        public static class TimeOutThread extends Thread {
            final long timeout;
            final MainThread controlledObj;
    
            TimeOutThread(long timeout, MainThread controlledObj) {
                setDaemon(true);
                this.timeout = timeout;
                this.controlledObj = controlledObj;
            }
    
            boolean isRunning = true;
    
            /**
             * If we done need the {@link TimeOutThread} thread, we may kill it.
             */
            public void kill() {
                isRunning = false;
                synchronized (this) {
                    notify();
                }
            }
    
            /**
             * 
             */
            @Override
            public void run() {
                long deltaT = 0l;
                try {
                    long start = System.currentTimeMillis();
                    while (isRunning && deltaT < timeout) {
                        synchronized (this) {
                            wait(Math.max(100, timeout - deltaT));
                        }
                        deltaT = System.currentTimeMillis() - start;
                    }
                } catch (InterruptedException e) {
                    // If the thread is interrupted,
                    // you may not want to kill the main thread,
                    // but probably yes.
                } finally {
                    isRunning = false;
                }
                controlledObj.kill();
            }
        }
    
        /**
         * Start the main task and wait for the end.
         * 
         * @param args
         * @throws FileNotFoundException
         */
        public static void main(String[] args) throws FileNotFoundException {
            long start = System.currentTimeMillis();
            MainThread main = new MainThread(new File(args[0]));
            main.start();
            try {
                while (main.isRunning) {
                    synchronized (main) {
                        main.wait(1000);
                    }
                }
                long stop = System.currentTimeMillis();
    
                if (main.everythingDone)
                    System.out.println("all done in " + (stop - start) + " ms.");
                else {
                    System.out.println("could not do everything in "
                            + (stop - start) + " ms.");
                    if (main.endedWithException != null)
                        main.endedWithException.printStackTrace();
                }
            } catch (InterruptedException e) {
                System.out.println("You've killed me!");
            }
        }
    }
    

    Regards

提交回复
热议问题