首页 > 代码库 > commons-io源码阅读心得

commons-io源码阅读心得

FileCleanTracker: 开启一个守护线程在后台默默的删除文件。

  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 import java.io.File; 20 import java.lang.ref.PhantomReference; 21 import java.lang.ref.ReferenceQueue; 22 import java.util.Collection; 23 import java.util.Vector; 24  25 /** 26  * Keeps track of files awaiting deletion, and deletes them when an associated 27  * marker object is reclaimed by the garbage collector. 28  * <p> 29  * This utility creates a background thread to handle file deletion. 30  * Each file to be deleted is registered with a handler object. 31  * When the handler object is garbage collected, the file is deleted. 32  * <p> 33  * In an environment with multiple class loaders (a servlet container, for 34  * example), you should consider stopping the background thread if it is no 35  * longer needed. This is done by invoking the method 36  * {@link #exitWhenFinished}, typically in 37  * {@link javax.servlet.ServletContextListener#contextDestroyed} or similar. 38  * 39  * @author Noel Bergman 40  * @author Martin Cooper 41  * @version $Id: FileCleaner.java 490987 2006-12-29 12:11:48Z scolebourne $ 42  */ 43 public class FileCleaningTracker { 44     /** 45      * Queue of <code>Tracker</code> instances being watched. 46      */ 47     ReferenceQueue /* Tracker */ q = new ReferenceQueue(); 48     /** 49      * Collection of <code>Tracker</code> instances in existence. 50      */ 51     final Collection /* Tracker */ trackers = new Vector();  // synchronized 52     /** 53      * Whether to terminate the thread when the tracking is complete. 54      */ 55     volatile boolean exitWhenFinished = false; 56     /** 57      * The thread that will clean up registered files. 58      */ 59     Thread reaper; 60  61     //----------------------------------------------------------------------- 62     /** 63      * Track the specified file, using the provided marker, deleting the file 64      * when the marker instance is garbage collected. 65      * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. 66      * 67      * @param file  the file to be tracked, not null 68      * @param marker  the marker object used to track the file, not null 69      * @throws NullPointerException if the file is null 70      */ 71     public void track(File file, Object marker) { 72         track(file, marker, (FileDeleteStrategy) null); 73     } 74  75     /** 76      * Track the specified file, using the provided marker, deleting the file 77      * when the marker instance is garbage collected. 78      * The speified deletion strategy is used. 79      * 80      * @param file  the file to be tracked, not null 81      * @param marker  the marker object used to track the file, not null 82      * @param deleteStrategy  the strategy to delete the file, null means normal 83      * @throws NullPointerException if the file is null 84      */ 85     public void track(File file, Object marker, FileDeleteStrategy deleteStrategy) { 86         if (file == null) { 87             throw new NullPointerException("The file must not be null"); 88         } 89         addTracker(file.getPath(), marker, deleteStrategy); 90     } 91  92     /** 93      * Track the specified file, using the provided marker, deleting the file 94      * when the marker instance is garbage collected. 95      * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. 96      * 97      * @param path  the full path to the file to be tracked, not null 98      * @param marker  the marker object used to track the file, not null 99      * @throws NullPointerException if the path is null100      */101     public void track(String path, Object marker) {102         track(path, marker, (FileDeleteStrategy) null);103     }104 105     /**106      * Track the specified file, using the provided marker, deleting the file107      * when the marker instance is garbage collected.108      * The speified deletion strategy is used.109      *110      * @param path  the full path to the file to be tracked, not null111      * @param marker  the marker object used to track the file, not null112      * @param deleteStrategy  the strategy to delete the file, null means normal113      * @throws NullPointerException if the path is null114      */115     public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {116         if (path == null) {117             throw new NullPointerException("The path must not be null");118         }119         addTracker(path, marker, deleteStrategy);120     }121 122     /**123      * Adds a tracker to the list of trackers.124      * 125      * @param path  the full path to the file to be tracked, not null126      * @param marker  the marker object used to track the file, not null127      * @param deleteStrategy  the strategy to delete the file, null means normal128      */129     private synchronized void addTracker(String path, Object marker, FileDeleteStrategy deleteStrategy) {130         // synchronized block protects reaper131         if (exitWhenFinished) {132             throw new IllegalStateException("No new trackers can be added once exitWhenFinished() is called");133         }134         if (reaper == null) {135             reaper = new Reaper();136             reaper.start();137         }138         trackers.add(new Tracker(path, deleteStrategy, marker, q));139     }140 141     //-----------------------------------------------------------------------142     /**143      * Retrieve the number of files currently being tracked, and therefore144      * awaiting deletion.145      *146      * @return the number of files being tracked147      */148     public int getTrackCount() {149         return trackers.size();150     }151 152     /**153      * Call this method to cause the file cleaner thread to terminate when154      * there are no more objects being tracked for deletion.155      * <p>156      * In a simple environment, you don‘t need this method as the file cleaner157      * thread will simply exit when the JVM exits. In a more complex environment,158      * with multiple class loaders (such as an application server), you should be159      * aware that the file cleaner thread will continue running even if the class160      * loader it was started from terminates. This can consitute a memory leak.161      * <p>162      * For example, suppose that you have developed a web application, which163      * contains the commons-io jar file in your WEB-INF/lib directory. In other164      * words, the FileCleaner class is loaded through the class loader of your165      * web application. If the web application is terminated, but the servlet166      * container is still running, then the file cleaner thread will still exist,167      * posing a memory leak.168      * <p>169      * This method allows the thread to be terminated. Simply call this method170      * in the resource cleanup code, such as {@link javax.servlet.ServletContextListener#contextDestroyed}.171      * One called, no new objects can be tracked by the file cleaner.172      */173     public synchronized void exitWhenFinished() {174         // synchronized block protects reaper175         exitWhenFinished = true;176         if (reaper != null) {177             synchronized (reaper) {178                 reaper.interrupt();179             }180         }181     }182 183     //-----------------------------------------------------------------------184     /**185      * The reaper thread.186      */187     private final class Reaper extends Thread {188         /** Construct a new Reaper */189         Reaper() {190             super("File Reaper");191             setPriority(Thread.MAX_PRIORITY);192             setDaemon(true);193         }194 195         /**196          * Run the reaper thread that will delete files as their associated197          * marker objects are reclaimed by the garbage collector.198          */199         public void run() {200             // thread exits when exitWhenFinished is true and there are no more tracked objects201             while (exitWhenFinished == false || trackers.size() > 0) {202                 Tracker tracker = null;203                 try {204                     // Wait for a tracker to remove.205                     tracker = (Tracker) q.remove();206                 } catch (Exception e) {207                     continue;208                 }209                 if (tracker != null) {210                     tracker.delete();211                     tracker.clear();212                     trackers.remove(tracker);213                 }214             }215         }216     }217 218     //-----------------------------------------------------------------------219     /**220      * Inner class which acts as the reference for a file pending deletion.221      */222     private static final class Tracker extends PhantomReference {223 224         /**225          * The full path to the file being tracked.226          */227         private final String path;228         /**229          * The strategy for deleting files.230          */231         private final FileDeleteStrategy deleteStrategy;232 233         /**234          * Constructs an instance of this class from the supplied parameters.235          *236          * @param path  the full path to the file to be tracked, not null237          * @param deleteStrategy  the strategy to delete the file, null means normal238          * @param marker  the marker object used to track the file, not null239          * @param queue  the queue on to which the tracker will be pushed, not null240          */241         Tracker(String path, FileDeleteStrategy deleteStrategy, Object marker, ReferenceQueue queue) {242             super(marker, queue);243             this.path = path;244             this.deleteStrategy = (deleteStrategy == null ? FileDeleteStrategy.NORMAL : deleteStrategy);245         }246 247         /**248          * Deletes the file associated with this tracker instance.249          *250          * @return <code>true</code> if the file was deleted successfully;251          *         <code>false</code> otherwise.252          */253         public boolean delete() {254             return deleteStrategy.deleteQuietly(new File(path));255         }256     }257 258 }
View Code