thread.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 467 行

JAVA
467
字号
/*
 * $Id: Thread.java,v 1.1 2003/11/25 11:42:00 epr Exp $
 */

package java.lang;

import org.jnode.vm.Unsafe;
import org.jnode.vm.VmSystem;
import org.jnode.vm.VmThread;

/**
 * Kore implementation of the <code>java.lang.Thread</code> class.
 * <p>
 * All native methods are indirected through <code>java.lang.NativeLang</code>.
 * 
 * @see java.lang.NativeLang
 * @version Kore 0.0.3, June 1997
 * @author Glynn Clements <a href="mailto:glynn@sensei.co.uk">glynn@sensei.co.uk</a>
 * @author E. Prangsma (connection to JNode)
 */
public class Thread implements Runnable {

	/** Is this a daemon thread? */
	private boolean daemon;
	/** The group this thread belongs to */
	private final ThreadGroup group;
	/** The name of this thread */
	private String name;
	/** A runnable target (if any) */
	private final Runnable target;
	/** The VM thread implementing this thread */
	private final VmThread vmThread;
	/** The context classloader of this thread */
	private ClassLoader contextClassLoader;
	/** The thread in which I was created */
	private final Thread parent;

	/**
	 * Number of threads created. Used only for generating "unique" names.
	 * 
	 * @see java.lang.Thread#autoName()
	 */
	private static int count = 0;

	public final static int MAX_PRIORITY = 10;
	public final static int MIN_PRIORITY = 1;
	public final static int NORM_PRIORITY = 5;

	/**
	 * Gets the active number of threads in the current thread's thread group.
	 * 
	 * @return the active number of threads in the current thread's thread group.
	 */
	public static int activeCount() {
		return currentThread().getThreadGroup().activeCount();
	}

	/**
	 * Generate a "unique" default name for a thread.
	 */
	private static synchronized String autoName() {
		return "Thread-" + (++count);
	}

	/**
	 * Gets the current thread.
	 * 
	 * @return
	 */
	public static Thread currentThread() {
		VmThread current = VmThread.currentThread();
		if (current != null) {
			return current.asThread();
		} else {
			return null;
		}
	}

	/**
	 * Prints a stack trace of the current thread.
	 */
	public static void dumpStack() {
		new Exception("Stack trace").printStackTrace();
	}

	public static int enumerate(Thread[] threads) {
		return currentThread().getThreadGroup().enumerate(threads);
	}

	public static boolean interrupted() {
		return currentThread().isInterrupted();
	}

	public static void sleep(long millis) throws InterruptedException {
		sleep(millis, 0);
	}

	/*
	 * XXX needs to be synchronized to avoid losing interrupts? it checks and sets state, which
	 * should be protected...
	 */
	public static void sleep(long millis, int nanos) throws InterruptedException {
		VmThread.currentThread().sleep(millis, nanos);
	}

	public final VmThread getVmThread() {
		return vmThread;
	}

	public static void yield() {
		VmThread.yield();
	}

	/**
	 * Create a new default instance
	 * 
	 * @see java.lang.Object#Object()
	 */
	public Thread() {
		this(null, null, autoName());
	}

	/**
	 * Create a new instance with a runnable as thread runner.
	 * 
	 * @param target
	 */
	public Thread(Runnable target) {
		this(null, target, autoName());
	}

	/**
	 * Create a new instance with a runnable as thread runner and a given name.
	 * 
	 * @param target
	 * @param name
	 */
	public Thread(Runnable target, String name) {
		this(null, target, name);
	}

	/**
	 * Create a new instance with a given name.
	 * 
	 * @param name
	 */
	public Thread(String name) {
		this(null, null, name);
	}

	/**
	 * Create a new instance with a given group as containing group and a runnable as thread
	 * runner.
	 * 
	 * @param group
	 * @param target
	 */
	public Thread(ThreadGroup group, Runnable target) {
		this(group, target, autoName());
	}

	/**
	 * Create a new instance with a given group as containing group, a runnable as thread runner
	 * and a given name.
	 * 
	 * @param group
	 * @param target
	 * @param name
	 */
	public Thread(ThreadGroup group, Runnable target, String name) {
		Thread current = currentThread();

		if (group != null) {
			group.checkAccess();
		} else {
			group = current.getThreadGroup();
		}

		if (group == null) {
			throw new InternalError("Live thread has invalid group: " + name);
		}

		group.add(this);

		this.group = group;
		this.target = target;
		this.name = name;
		this.parent = current;

		this.daemon = current.isDaemon();

		this.vmThread = Unsafe.getCurrentProcessor().createThread(this);
		this.vmThread.setPriority(current.getPriority());
	}

	/**
	 * Create a new instance with a given group as containing group and a given name.
	 * 
	 * @param group
	 * @param name
	 */
	public Thread(ThreadGroup group, String name) {
		this(group, null, name);
	}

	/**
	 * Create a new thread from a given VmThread. Only used for the main thread.
	 * 
	 * @param vmThread
	 * @throws IllegalArgumentException
	 *             If the given vmThread is not the root thread or the given vmThread already has
	 *             an associated java thread.
	 */
	public Thread(VmThread vmThread) throws IllegalArgumentException {
		if (vmThread.hasJavaThread()) {
			throw new IllegalArgumentException("vmThread has already a java thread associated with it");
		}
		this.vmThread = vmThread;
		this.group = ThreadGroup.getRootGroup();
		this.group.add(this);
		this.name = "System";
		this.target = null;
		this.parent = null;
	}

	/**
	 * Has the current execution context enough access to modify this object?
	 */
	public void checkAccess() {
		SecurityManager sm = System.getSecurityManager();
		if (sm != null)
			sm.checkAccess(this);
	}

	public int countStackFrames() {
		return vmThread.countStackFrames();
	}

	/**
	 * Destroys this thread, without any cleanup. Any monitors it has locked remain locked. (This
	 * method is not implemented.)
	 */
	public void destroy() {
		vmThread.destroy();
	}

	/**
	 * Method called only by the VM to let the object do some java-level cleanup.
	 */
	public final void onExit() {
		if (vmThread.isStopping()) {
			group.remove(this);
		}
	}

	/**
	 * Gets the context classloader for this thread. The context ClassLoader is provided by the
	 * creator of the thread for use by code running in this thread when loading classes and
	 * resources. If not set, the default is the ClassLoader context of the parent Thread. The
	 * context ClassLoader of the primordial thread is typically set to the class loader used to
	 * load the application. First, if there is a security manager, and the caller's class loader
	 * is not null and the caller's class loader is not the same as or an ancestor of the context
	 * class loader for the thread whose context class loader is being requested, then the security
	 * manager's checkPermission method is called with a <code>RuntimePermission("getClassLoader")</code>
	 * permission to see if it's ok to get the context ClassLoader.
	 * 
	 * @return
	 */
	public ClassLoader getContextClassLoader() {
		if (contextClassLoader != null) {
			return contextClassLoader;
		} else if (parent != null) {
			return parent.getContextClassLoader();
		} else {
			return getClass().getClassLoader();
		}
	}

	/**
	 * Sets the context ClassLoader for this Thread. The context ClassLoader can be set when a
	 * thread is created, and allows the creator of the thread to provide the appropriate class
	 * loader to code running in the thread when loading classes and resources.
	 * 
	 * First, if there is a security manager, its checkPermission method is called with a
	 * RuntimePermission("setContextClassLoader") permission to see if it's ok to set the context
	 * ClassLoader.
	 * 
	 * @param loader
	 */
	public void setContextClassLoader(ClassLoader loader) throws SecurityException {
		final SecurityManager sm = System.getSecurityManager();
		if (sm != null) {
			sm.checkPermission(new RuntimePermission("setContextClassLoader"));
		}
		this.contextClassLoader = loader;
	}

	/**
	 * Gets the name of this thread
	 * 
	 * @return
	 */
	public final String getName() {
		return name;
	}

	/**
	 * Gets the priority of this thread
	 * 
	 * @return
	 */
	public final int getPriority() {
		return vmThread.getPriority();
	}

	/**
	 * Gets the group this thread is a child of.
	 * 
	 * @return
	 */
	public final ThreadGroup getThreadGroup() {
		return isAlive() ? group : null;
	}

	/**
	 * Interrupt this thread.
	 */
	public void interrupt() {
		vmThread.interrupt();
	}

	/**
	 * Returns <code>true</code> if the thread represented by this object is running (including
	 * suspended, asleep, or interrupted.) Returns <code>false</code> if the thread hasn't be
	 * started yet, is stopped or destroyed.
	 * 
	 * @return <code>true</code> if thread is alive, <code>false</code> if not.
	 * @see #start()
	 * @see #stop()
	 * @see #suspend()
	 * @see #interrupt()
	 */
	public final boolean isAlive() {
		return vmThread.isAlive();
	}

	public final boolean isDaemon() {
		return daemon;
	}

	public boolean isInterrupted() {
		return vmThread.isInterrupted();
	}

	/**
	 * Is this thread waiting in a monitor?
	 * 
	 * @return boolean
	 */
	public boolean isWaiting() {
		return vmThread.isWaiting();
	}

	/**
	 * Is this thread in the running state?
	 * 
	 * @return boolean
	 */
	public final boolean isRunning() {
		return vmThread.isRunning() || vmThread.isYielding();
	}

	/**
	 * Join with the current thread. The calling thread will block until this thread dies.
	 * 
	 * XXX wait()s on the thread. Seems like this would cause a spurious wakeup if some code
	 * synchronizes on the thread and uses wait/notify for some other purpose.
	 */
	public final synchronized void join() throws InterruptedException {
		while (isAlive()) {
			/* wait sets this.state = WAITING; */
			wait();
			/* wait sets this.state = RUNNING; */
		}
	}

	public final synchronized void join(long millis) throws InterruptedException {
		if (millis == 0) {
			join();
		} else {
			final long stopTime = VmSystem.currentKernelMillis() + millis;
			while (isAlive() && (millis > 0)) {
				/* wait sets this.state = WAITING; */
				wait(millis);
				millis = stopTime - VmSystem.currentKernelMillis();
				/* wait sets this.state = RUNNING; */
			}
		}
	}

	public final void join(long millis, int nanos) throws InterruptedException {
		join(millis);
	}

	public final void resume() {
		vmThread.resume();
	}

	public void run() {
		if (target != null)
			target.run();
	}

	public final void setDaemon(boolean daemon) {
		checkAccess();
		if (isAlive())
			throw new IllegalThreadStateException("already started");
		this.daemon = daemon;
	}

	public final void setName(String name) {
		checkAccess();
		this.name = name;
	}

	public final void setPriority(int priority) {
		vmThread.setPriority(priority);
	}

	/**
	 * Start this thread object. After calling this method there will be a new active thread in the
	 * system (assuming things go well.) The <code>Runnable</code> object, or the Thread's <code>run()</code>
	 * method will be started in a new thread.
	 *  
	 */
	public void start() {
		vmThread.start();
	}

	public final void stop() {
		vmThread.stop(new ThreadDeath());
	}

	/**
	 * The polite way to kill a thread.
	 * 
	 * @param error
	 *            <code>Throwable</code> to toss in stopped thread.
	 */
	public final void stop(Throwable error) {
		checkAccess();

		if (error == null) {
			throw new NullPointerException("Throwable is null");
		}
		vmThread.stop(error);
	}

	public final void suspend() {
		vmThread.suspend();
	}

	public String toString() {
		return "Thread[" + name + "," + getPriority() + "," + group.getName() + "," + vmThread + "]";
	}
}

⌨️ 快捷键说明

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