edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.java Source code

Java tutorial

Introduction

Here is the source code for edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.java

Source

/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.utils.threads;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A simple base class that will allow us to find the background threads and
 * check their current status.
 */
public class VitroBackgroundThread extends Thread {
    Log log = LogFactory.getLog(VitroBackgroundThread.class);

    private static final ConcurrentLinkedQueue<WeakReference<VitroBackgroundThread>> allThreads = new ConcurrentLinkedQueue<WeakReference<VitroBackgroundThread>>();

    /**
     * Get a list of all VitroBackgroundThreads that have not been garbage-collected.
     */
    public static List<VitroBackgroundThread> getThreads() {
        List<VitroBackgroundThread> list = new ArrayList<VitroBackgroundThread>();
        for (WeakReference<VitroBackgroundThread> ref : allThreads) {
            VitroBackgroundThread t = ref.get();
            if (t != null) {
                list.add(t);
            }
        }
        return list;
    }

    /**
     * Get a list of all VitroBackgroundThreads that have not died.
     */
    public static List<VitroBackgroundThread> getLivingThreads() {
        List<VitroBackgroundThread> list = new ArrayList<VitroBackgroundThread>();
        for (VitroBackgroundThread t : getThreads()) {
            if (t.isAlive()) {
                list.add(t);
            }
        }
        return list;
    }

    public enum WorkLevel {
        IDLE, WORKING
    }

    private volatile WorkLevelStamp stamp = new WorkLevelStamp(WorkLevel.IDLE);

    public VitroBackgroundThread(String name) {
        super(name);
        allThreads.add(new WeakReference<VitroBackgroundThread>(this));
    }

    public VitroBackgroundThread(Runnable target, String name) {
        super(target, name);
        allThreads.add(new WeakReference<VitroBackgroundThread>(this));
    }

    public void setWorkLevel(WorkLevel level, String... flags) {
        log.debug("Set work level on '" + this.getName() + "' to " + level + ", flags=" + flags);
        stamp = new WorkLevelStamp(level, flags);
    }

    public WorkLevelStamp getWorkLevel() {
        return stamp;
    }

    /**
     * An immutable object that holds both the current work level and the time
     * that it was set.
     * 
     * Particular threads may want to assign additional state using zero or more
     * "flags".
     */
    public static class WorkLevelStamp {
        private final WorkLevel level;
        private final long since;
        private final List<String> flags;

        public WorkLevelStamp(WorkLevel level, String... flags) {
            this.level = level;
            this.since = System.currentTimeMillis();
            this.flags = Collections.unmodifiableList(Arrays.asList(flags));
        }

        public WorkLevel getLevel() {
            return level;
        }

        public Date getSince() {
            return new Date(since);
        }

        public Collection<String> getFlags() {
            return flags;
        }
    }

    /**
     * A factory class, for use in Executors, that creates threads with
     * successive names.
     */
    public static class Factory implements ThreadFactory {
        private final String threadName;
        private final AtomicInteger index;

        public Factory(String threadName) {
            this.threadName = threadName;
            this.index = new AtomicInteger();
        }

        @Override
        public Thread newThread(Runnable r) {
            return new VitroBackgroundThread(r, threadName + "_" + index.getAndIncrement());
        }

    }

}