`

Thread 源码分析

    博客分类:
  • java
阅读更多
线程是程序的一个执行流程,Java虚拟机允许多个线程同时并发执行。

1. 构造方法
	public Thread() {
		init(null, null, "Thread-" + nextThreadNum(), 0);
	}

	// target - 任务
	public Thread(Runnable target) {
		init(null, target, "Thread-" + nextThreadNum(), 0);
	}

	// group - 线程组,target - 任务
	public Thread(ThreadGroup group, Runnable target) {
		init(group, target, "Thread-" + nextThreadNum(), 0);
	}

	// name - 线程名称
	public Thread(String name) {
		init(null, null, name, 0);
	}

	// group - 线程组,name - 线程名称
	public Thread(ThreadGroup group, String name) {
		init(group, null, name, 0);
	}

	// target - 任务,name - 线程名称
	public Thread(Runnable target, String name) {
		init(null, target, name, 0);
	}

	// group - 线程组,target - 任务,name - 线程名称
	public Thread(ThreadGroup group, Runnable target, String name) {
		init(group, target, name, 0);
	}

	// group - 线程组,target - 任务,name - 线程名称, stackSize - 栈大小
	// 这里的stackSize只是提供一个参考值,和平台相关,JVM根据情况会做适当的调整。
	// stackSize大一些,线程就会不容易抛StackOverflowError。
	// stackSize小一些,多个线程并发执行不容易抛OutOfMemoryError。
	// 栈大小,最大递归深度和并发水平是和平台相关的。
	public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
		init(group, target, name, stackSize);
	}


2. 线程启动
	public synchronized void start() {
		if (threadStatus != 0 || this != me)
			throw new IllegalThreadStateException();
		group.add(this);
		start0();
		if (stopBeforeStart) {
			stop0(throwableFromStop);
		}
	}

	private native void start0();


3. 任务执行

一般由JVM来调用该方法,也可以手动调用。

a. 如果子类覆盖了run()方法,则调用子类的run()
b. 如果a不成立:
   b1. 指定了target,则调用target的run()
   b2. 没有指定target,该方法不做任何事并返回
	public void run() {
		if (target != null) {
			target.run();
		}
	}


所以,下面MyThread的run方法会执行:
public class MyThread extends Thread {
	public void run() {
		System.out.println("MyThread.run()");
	}
}

new MyThread(new Runnable() {
	public void run() {
		System.out.println("Runnable.run()");
	}
}).start();


4. 清理工作

由系统来调用该方法,在线程退出之前清理分配的资源。
	private void exit() {
		if (group != null) {
			group.remove(this);
			group = null;
		}
	
		target = null;
		threadLocals = null;
		inheritableThreadLocals = null;
		inheritedAccessControlContext = null;
		blocker = null;
		uncaughtExceptionHandler = null;
	}


5. yield方法

使当前执行线程暂停一会,让其它线程得以执行。只是临时让出时间片,不会释放拥有的锁。
	public static native void yield();


6. sleep方法

使当前执行线程休眠指定的时间,不释放持有的锁。
	public static native void sleep(long millis) throws InterruptedException;

	public static void sleep(long millis, int nanos) 
		throws InterruptedException {
		if (millis < 0) {
			throw new IllegalArgumentException("timeout value is negative");
		}

		if (nanos < 0 || nanos > 999999) {
			throw new IllegalArgumentException(
				"nanosecond timeout value out of range");
		}

		if (nanos >= 500000 || (nanos != 0 && millis == 0)) { // 纳秒四舍五入,或者毫秒为0且纳秒不为0时
			millis++;
		}

		sleep(millis);
	}


7. join方法

等待该线程执行,直到超时或者终止。

可以作为线程通信的一种方式:A线程调用B线程的join方法(阻塞),等待B完成后再往下执行。

	public final synchronized void join(long millis) 
		throws InterruptedException {
		long base = System.currentTimeMillis();
		long now = 0;

		if (millis < 0) {
			throw new IllegalArgumentException("timeout value is negative");
		}

		if (millis == 0) { // 0代表没有时间限制
			while (isAlive()) {
				wait(0); // 无限期的等待
			}
		} else {
			while (isAlive()) {
				long delay = millis - now;
				if (delay <= 0) {
					break;
				}
				wait(delay); // 有限期的等待
				now = System.currentTimeMillis() - base;
			}
		}
	}

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

		if (millis < 0) {
			throw new IllegalArgumentException("timeout value is negative");
		}

		if (nanos < 0 || nanos > 999999) {
			throw new IllegalArgumentException(
				"nanosecond timeout value out of range");
		}

		if (nanos >= 500000 || (nanos != 0 && millis == 0)) { // 纳秒四舍五入,或者毫秒为0且纳秒不为0时
			millis++;
		}

		join(millis);
	}

	public final void join() throws InterruptedException {
		join(0);
	}


8. 中断
	public void interrupt() {
		if (this != Thread.currentThread())
			checkAccess();

		synchronized (blockerLock) {
			Interruptible b = blocker;
			if (b != null) {
				interrupt0();		// Just to set the interrupt flag
				b.interrupt();
				return;
			}
		}
		interrupt0();
	}

	// 静态方法:查看当前线程是否中断,并且清除中断标志。
	public static boolean interrupted() {
		return currentThread().isInterrupted(true);
	}

	// 查看该线程是否中断,但不清除中断标志。
	public boolean isInterrupted() {
		return isInterrupted(false);
	}

	private native boolean isInterrupted(boolean ClearInterrupted);


9. 守护/普通进程

JVM有很多守护进程:如垃圾回收线程等。没有前台(Non-Daemon)线程时,JVM会退出。

    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }


10. 上下文类加载器
	public ClassLoader getContextClassLoader() {
		if (contextClassLoader == null)
			return null;
		SecurityManager sm = System.getSecurityManager();
		if (sm != null) {
			ClassLoader ccl = ClassLoader.getCallerClassLoader(); // 调用者的类加载器
			if (ccl != null && ccl != contextClassLoader && 
				!contextClassLoader.isAncestor(ccl)) { // 调用者得类加载器不为空,且不和该线程的类加载器相同,也不是该类加载器的祖先时
				sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
			}
		}
		return contextClassLoader;
	}

	public void setContextClassLoader(ClassLoader cl) {
		SecurityManager sm = System.getSecurityManager();
		if (sm != null) {
			sm.checkPermission(new RuntimePermission("setContextClassLoader"));
		}
		contextClassLoader = cl;
	}


11. 线程的优先级
	// 最小的优先级
	public final static int MIN_PRIORITY = 1;

	// 正常的优先级
	public final static int NORM_PRIORITY = 5;

	// 最大的优先级
	public final static int MAX_PRIORITY = 10;

	public final void setPriority(int newPriority) {
		ThreadGroup g;
		checkAccess();
		if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
			throw new IllegalArgumentException();
		}
		if((g = getThreadGroup()) != null) {
			if (newPriority > g.getMaxPriority()) {
				newPriority = g.getMaxPriority();
			}
			setPriority0(priority = newPriority);
		}
	}

a. 线程的优先级在不同的系统平台上,对应的系统优先级会不同;可能多个优先级对应同一个系统优先级。

b. 优先级高的线程并不一定会优先执行,这个由JVM来解译并向系统提供参考。

12. 线程的状态

	public enum State {
		// 新建的线程,还没调用start()方法
		NEW,

		// 可以运行,需要等到其它资源(如CPU)就绪才能运行
		RUNNABLE,

		// 线程调用wait()后等待内置锁进入同步块或方法
		BLOCKED,

		// 在调用无参的wait(),Thread.join()或LockSupport.lock()方法后进入等待状态
		WAITING,

		// 调用Thread.sleep(), 有时间参数的wait(), 有时间参数的Thread.join(), LockSupport.parkNanos或LockSupport.parkUtil方法后进行有期限的等待状态
		TIMED_WAITING,

		// 执行完毕的线程状态
		TERMINATED;
	}

	public State getState() {
		// get current thread state
		return sun.misc.VM.toThreadState(threadStatus);
	}


13. 未检查异常处理器
	public interface UncaughtExceptionHandler { 
		void uncaughtException(Thread t, Throwable e);
	}

	private volatile UncaughtExceptionHandler uncaughtExceptionHandler;

	private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

	// 设置线程默认的未检查异常处理器
	public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
		SecurityManager sm = System.getSecurityManager();
		if (sm != null) {
			sm.checkPermission(
				new RuntimePermission("setDefaultUncaughtExceptionHandler")
			);
		}

		defaultUncaughtExceptionHandler = eh;
	}

	public UncaughtExceptionHandler getUncaughtExceptionHandler() { 
		return uncaughtExceptionHandler != null ?
			uncaughtExceptionHandler : group;
	}

	public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { 
		checkAccess();
		uncaughtExceptionHandler = eh;
	}

	// 只由JVM调用
	private void dispatchUncaughtException(Throwable e) {
		getUncaughtExceptionHandler().uncaughtException(this, e);
	}
分享到:
评论
1 楼 santouren 2016-06-23  
感谢整理,Java初学者受益良多

相关推荐

Global site tag (gtag.js) - Google Analytics