Coverage Report - org.apache.commons.io.ThreadMonitor
 
Classes in this File Line Coverage Branch Coverage Complexity
ThreadMonitor
100%
26/26
83%
5/6
1,667
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.io;
 18  
 
 19  
 /**
 20  
  * Monitors a thread, interrupting it if it reaches the specified timeout.
 21  
  * <p>
 22  
  * This works by sleeping until the specified timeout amount and then
 23  
  * interrupting the thread being monitored. If the thread being monitored
 24  
  * completes its work before being interrupted, it should <code>interrupt()</code>
 25  
  * the <i>monitor</i> thread.
 26  
  * </p>
 27  
  * 
 28  
  * <pre>
 29  
  *       long timeoutInMillis = 1000;
 30  
  *       try {
 31  
  *           Thread monitor = ThreadMonitor.start(timeoutInMillis);
 32  
  *           // do some work here
 33  
  *           ThreadMonitor.stop(monitor);
 34  
  *       } catch (InterruptedException e) {
 35  
  *           // timed amount was reached
 36  
  *       }
 37  
  * </pre>
 38  
  *
 39  
  */
 40  
 class ThreadMonitor implements Runnable {
 41  
 
 42  
     private final Thread thread;
 43  
     private final long timeout;
 44  
 
 45  
     /**
 46  
      * Start monitoring the current thread.
 47  
      *
 48  
      * @param timeout The timeout amount in milliseconds
 49  
      * or no timeout if the value is zero or less
 50  
      * @return The monitor thread or {@code null}
 51  
      * if the timeout amount is not greater than zero
 52  
      */
 53  
     public static Thread start(final long timeout) {
 54  84
         return start(Thread.currentThread(), timeout);
 55  
     }
 56  
 
 57  
     /**
 58  
      * Start monitoring the specified thread.
 59  
      *
 60  
      * @param thread The thread The thread to monitor
 61  
      * @param timeout The timeout amount in milliseconds
 62  
      * or no timeout if the value is zero or less
 63  
      * @return The monitor thread or {@code null}
 64  
      * if the timeout amount is not greater than zero
 65  
      */
 66  
     public static Thread start(final Thread thread, final long timeout) {
 67  84
         Thread monitor = null;
 68  84
         if (timeout > 0) {
 69  4
             final ThreadMonitor timout = new ThreadMonitor(thread, timeout);
 70  4
             monitor = new Thread(timout, ThreadMonitor.class.getSimpleName());
 71  4
             monitor.setDaemon(true);
 72  4
             monitor.start();
 73  
         }
 74  84
         return monitor;
 75  
     }
 76  
 
 77  
     /**
 78  
      * Stop monitoring the specified thread.
 79  
      *
 80  
      * @param thread The monitor thread, may be {@code null}
 81  
      */
 82  
     public static void stop(final Thread thread) {
 83  82
         if (thread != null) {
 84  2
             thread.interrupt();
 85  
         }
 86  82
     }
 87  
 
 88  
     /**
 89  
      * Construct and new monitor.
 90  
      *
 91  
      * @param thread The thread to monitor
 92  
      * @param timeout The timeout amount in milliseconds
 93  
      */
 94  4
     private ThreadMonitor(final Thread thread, final long timeout) {
 95  4
         this.thread = thread;
 96  4
         this.timeout = timeout;
 97  4
     }
 98  
 
 99  
     /**
 100  
      * Sleep until the specified timeout amount and then
 101  
      * interrupt the thread being monitored.
 102  
      *
 103  
      * @see Runnable#run()
 104  
      */
 105  
     @Override
 106  
     public void run() {
 107  
         try {
 108  4
             sleep(timeout);
 109  2
             thread.interrupt();
 110  2
         } catch (final InterruptedException e) {
 111  
             // timeout not reached
 112  2
         }
 113  4
     }
 114  
 
 115  
     /**
 116  
      * Sleep for a guaranteed minimum number of milliseconds unless interrupted.
 117  
      *
 118  
      * This method exists because Thread.sleep(100) can sleep for 0, 70, 100 or 200ms or anything else
 119  
      * it deems appropriate. Read the docs on Thread.sleep for further interesting details.
 120  
      *
 121  
      * @param ms the number of milliseconds to sleep for
 122  
      * @throws InterruptedException if interrupted
 123  
      */
 124  
     private static void sleep(long ms) throws InterruptedException {
 125  4
         long finishAt = System.currentTimeMillis() + ms;
 126  4
         long remaining = ms;
 127  
         do {
 128  4
             Thread.sleep(remaining);
 129  2
             remaining = finishAt - System.currentTimeMillis();
 130  2
         } while (remaining > 0);
 131  2
     }
 132  
 
 133  
 
 134  
 }