首页 > 代码库 > 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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。