imagefetcher.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 355 行

JAVA
355
字号
/* * @(#)ImageFetcher.java	1.29 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  * */package sun.awt.image;import java.util.Vector;import sun.awt.AppContext;import java.security.AccessController;import java.security.PrivilegedAction;/**  * An ImageFetcher is a thread used to fetch ImageFetchable objects.  * Once an ImageFetchable object has been fetched, the ImageFetcher  * thread may also be used to animate it if necessary, via the  * startingAnimation() / stoppingAnimation() methods.  *   * There can be up to FetcherInfo.MAX_NUM_FETCHERS_PER_APPCONTEXT  * ImageFetcher threads for each AppContext.  A per-AppContext queue  * of ImageFetchables is used to track objects to fetch.  *   */class ImageFetcher extends Thread {    static final int HIGH_PRIORITY = 8;    static final int LOW_PRIORITY = 3;    static final int ANIM_PRIORITY = 2;    static final int TIMEOUT = 5000; // Time in milliseconds to wait for an				     // ImageFetchable to be added to the				     // queue before an ImageFetcher dies    /**      * Constructor for ImageFetcher -- only called by add() below.      */    private ImageFetcher(ThreadGroup threadGroup, int index) {	super(threadGroup, "Image Fetcher " + index);	setDaemon(true);    }    /**      * Adds an ImageFetchable to the queue of items to fetch.  Instantiates      * a new ImageFetcher if it's reasonable to do so.      */    public static void add(ImageFetchable src) {        final FetcherInfo info = FetcherInfo.getFetcherInfo();        synchronized(info.waitList) {            if (!info.waitList.contains(src)) {                info.waitList.addElement(src);                if (info.numWaiting == 0 &&                            info.numFetchers < info.fetchers.length) {                    createFetchers(info);                }                info.waitList.notify();            }        }    }    /**      * Removes an ImageFetchable from the queue of items to fetch.      */    public static void remove(ImageFetchable src) {	final FetcherInfo info = FetcherInfo.getFetcherInfo();	synchronized(info.waitList) {	    if (info.waitList.contains(src)) {		info.waitList.removeElement(src);	    }	}    }    /**      * Checks to see if the given thread is one of the ImageFetchers.      */    public static boolean isFetcher(Thread t) {	final FetcherInfo info = FetcherInfo.getFetcherInfo();	synchronized(info.waitList) {	    for (int i = 0; i < info.fetchers.length; i++) {		if (info.fetchers[i] == t) {		    return true;		}	    }	}	return false;    }    /**      * Checks to see if the current thread is one of the ImageFetchers.      */    public static boolean amFetcher() {	return isFetcher(Thread.currentThread());    }    /**      * Returns the next ImageFetchable to be processed.  If TIMEOUT      * elapses in the mean time, or if the ImageFetcher is interrupted,      * null is returned.      */    private static ImageFetchable nextImage() {	final FetcherInfo info = FetcherInfo.getFetcherInfo();	synchronized(info.waitList) {	    ImageFetchable src = null;	    long end = System.currentTimeMillis() + TIMEOUT;	    while (src == null) {		while (info.waitList.size() == 0) {		    long now = System.currentTimeMillis();		    if (now >= end) {			return null;		    }		    try {			info.numWaiting++;			info.waitList.wait(end - now);		    } catch (InterruptedException e) {			// A normal occurrence as an AppContext is disposed			return null;		    } finally {			info.numWaiting--;		    }		}		src = (ImageFetchable) info.waitList.elementAt(0);		info.waitList.removeElement(src);	    }	    return src;	}    }    /**      * The main run() method of an ImageFetcher Thread.  Calls fetchloop()      * to do the work, then removes itself from the array of ImageFetchers.      */    public void run() {	final FetcherInfo info = FetcherInfo.getFetcherInfo();	try {	    fetchloop();	} catch (Exception e) {	    e.printStackTrace();	} finally {	    synchronized(info.waitList) {		Thread me = Thread.currentThread();		for (int i = 0; i < info.fetchers.length; i++) {		    if (info.fetchers[i] == me) {			info.fetchers[i] = null;			info.numFetchers--;		    }		}	    }	}    }    /**      * The main ImageFetcher loop.  Repeatedly calls nextImage(), and      * fetches the returned ImageFetchable objects until nextImage()      * returns null.      */    private void fetchloop() {	Thread me = Thread.currentThread();	while (isFetcher(me)) {            // 6263016: Problems with ImageFetcher and MediaTracker.            // See fix below for 4789067.            /*	    if (Thread.interrupted())		return; // Bail if interrupted            */	    // we're ignoring the return value and just clearing	    // the interrupted flag, instead of bailing out if	    // the fetcher was interrupted, as we used to, 	    // because there may be other images waiting	    // to be fetched (see 4789067)	    me.interrupted();	    me.setPriority(HIGH_PRIORITY);	    ImageFetchable src = nextImage();	    if (src == null) {		return;	    }	    try {		src.doFetch();	    } catch (Exception e) {		System.err.println("Uncaught error fetching image:");		e.printStackTrace();	    }	    stoppingAnimation(me);	}    }    /**      * Recycles this ImageFetcher thread as an image animator thread.      * Removes this ImageFetcher from the array of ImageFetchers, and      * resets the thread name to "ImageAnimator".      */    static void startingAnimation() {        final FetcherInfo info = FetcherInfo.getFetcherInfo();        Thread me = Thread.currentThread();        synchronized(info.waitList) {            for (int i = 0; i < info.fetchers.length; i++) {                if (info.fetchers[i] == me) {                    info.fetchers[i] = null;                    info.numFetchers--;                    me.setName("Image Animator " + i);                    if(info.waitList.size() > info.numWaiting) {                       createFetchers(info);                    }                    return;                }            }        }        me.setPriority(ANIM_PRIORITY);        me.setName("Image Animator");    }    /**      * Returns this image animator thread back to service as an ImageFetcher      * if possible.  Puts it back into the array of ImageFetchers and sets      * the thread name back to "Image Fetcher".  If there are already the      * maximum number of ImageFetchers, this method simply returns, and      * fetchloop() will drop out when it sees that this thread isn't one of      * the ImageFetchers, and this thread will die.      */    private static void stoppingAnimation(Thread me) {	final FetcherInfo info = FetcherInfo.getFetcherInfo();	synchronized(info.waitList) {	    int index = -1;	    for (int i = 0; i < info.fetchers.length; i++) {		if (info.fetchers[i] == me) {		    return;		}		if (info.fetchers[i] == null) {		    index = i;		}	    }	    if (index >= 0) {		info.fetchers[index] = me;		info.numFetchers++;		me.setName("Image Fetcher " + index);		return;	    }	}    }    /**      * Create and start ImageFetcher threads in the appropriate ThreadGroup.      */    private static void createFetchers(final FetcherInfo info) {       // We need to instantiate a new ImageFetcher thread.       // First, figure out which ThreadGroup we'll put the       // new ImageFetcher into       final AppContext appContext = AppContext.getAppContext();       ThreadGroup threadGroup = appContext.getThreadGroup();       ThreadGroup fetcherThreadGroup;       try {          if (threadGroup.getParent() != null) {             // threadGroup is not the root, so we proceed             fetcherThreadGroup = threadGroup;          } else {             // threadGroup is the root ("system") ThreadGroup.             // We instead want to use its child: the "main"             // ThreadGroup.  Thus, we start with the current             // ThreadGroup, and go up the tree until             // threadGroup.getParent().getParent() == null.             threadGroup = Thread.currentThread().getThreadGroup();             ThreadGroup parent = threadGroup.getParent();             while ((parent != null)                  && (parent.getParent() != null)) {                  threadGroup = parent;                  parent = threadGroup.getParent();             }             fetcherThreadGroup = threadGroup;         }       } catch (SecurityException e) {         // Not allowed access to parent ThreadGroup -- just use         // the AppContext's ThreadGroup         fetcherThreadGroup = appContext.getThreadGroup();       }       final ThreadGroup fetcherGroup = fetcherThreadGroup;       java.security.AccessController.doPrivileged(         new java.security.PrivilegedAction() {         public Object run() {             for (int i = 0; i < info.fetchers.length; i++) {               if (info.fetchers[i] == null) {                   info.fetchers[i] = new ImageFetcher(                           fetcherGroup, i);                   info.fetchers[i].start();                   info.numFetchers++;                   break;               }             }          return null;        }       });      return;    }}/**  * The FetcherInfo class encapsulates the per-AppContext ImageFetcher  * information.  This includes the array of ImageFetchers, as well as  * the queue of ImageFetchable objects.  */class FetcherInfo {    static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;    Thread[] fetchers;    int numFetchers;    int numWaiting;    Vector waitList;    private FetcherInfo() {	fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];	numFetchers = 0;	numWaiting = 0;	waitList = new Vector();    }    /* The key to put()/get() the FetcherInfo into/from the AppContext. */    private static final Object FETCHER_INFO_KEY =					new StringBuffer("FetcherInfo");    static FetcherInfo getFetcherInfo() {	AppContext appContext = AppContext.getAppContext();	synchronized(appContext) {	    FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);	    if (info == null) {		info = new FetcherInfo();		appContext.put(FETCHER_INFO_KEY, info);	    }	    return info;	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?