`

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初学者受益良多

相关推荐

    RT-Thread源代码

    由于上传大小限制,这是第一部份。要把part1,2,3一起下载并解压。

    ThreadX_源码.rar

    threadx 源码

    arm学习报告3_BIOS源码分析

    在深入探讨ARM BIOS源码分析之前,我们先要理解几个基本概念。ARM是一种广泛应用于嵌入式系统、移动设备和服务器等领域的精简指令集架构(RISC)。BIOS(基本输入输出系统)是计算机启动时运行的第一段软件,负责...

    ZLMediaKit源码分析

    《ZLMediaKit源码分析》 ZLMediaKit是一个开源的媒体服务器框架,它主要用于音视频流的推送和播放,支持RTMP、HLS、HTTP-FLV等多种协议。本文将深入分析其架构和主要模块,以帮助读者理解其工作原理。 1. 引言 ...

    Libevent源码分析 pdf文档 带目录

    在深入Libevent源码分析之前,需要了解它的核心概念,主要包括事件循环、事件处理器、IO事件、定时器事件、信号事件等。事件循环是Libevent的中枢,它在后台运行,检测事件源的变化,并触发相应的事件处理器。事件...

    rt-thread内核源码

    《深入解析rt-thread内核源码》 rt-thread是一个开源、免费、实时性强、可裁剪的嵌入式操作系统内核,它具有轻量...通过对rt-thread内核源码的分析和实践,开发者可以更好地利用rt-thread构建高效、稳定的嵌入式应用。

    JUC并发编程与源码分析视频课.zip

    《JUC并发编程与源码分析视频课》是一门深入探讨Java并发编程的课程,主要聚焦于Java Util Concurrency(JUC)库的使用和源码解析。JUC是Java平台提供的一组高级并发工具包,它极大地简化了多线程编程,并提供了更...

    ThreadX 源码

    在分析源码时,可以逐步理解各个模块的功能,尝试修改部分代码并进行调试,以加深对ThreadX工作原理的理解。同时,熟悉RTOS的设计模式和编程范式对于开发和优化嵌入式应用是至关重要的。通过深入研究ThreadX源码,...

    threadx 源码

    10. **调试工具**:ThreadX可能还包括了一些调试辅助工具,如日志记录、性能分析等功能。通过阅读这部分源码,开发者可以学习到如何在实际项目中进行问题排查。 通过深入研究ThreadX源码,开发者不仅可以获得关于...

    多线程实时操作系统ThreadX源码 使用说明,绝对超值(展.rar

    ThreadX是优秀的硬实时操作系统(RTOS),适用于深嵌入式应用中,具有规模小、实时性强、可靠性高、无产品版权费、易于使用等特点,并且支持大量的处理器和SoC...多线程实时操作系统ThreadX源码 使用说明, 非常适合于学习

    ReentrantLock源码分析

    ### ReentrantLock源码分析 #### 一、ReentrantLock简介 ReentrantLock是一个基于`AbstractQueuedSynchronizer`(AQS)实现的高级锁工具类。与传统的synchronized关键字相比,ReentrantLock提供了更多控制手段,比如...

    RTThread网络模块demo源码

    通过阅读和分析demo源码,开发者可以掌握如何在RTThread上编写网络应用程序。 总的来说,"RTThread网络模块demo源码"是一个学习和实践网络编程的好资料。它涵盖了从网络接口到高层应用的各种知识点,对于嵌入式系统...

    DSS源码分析汇总精华

    《DSS源码分析汇总精华》 Apple的DSS(Darwin Stream Server)是业界知名的流媒体服务器,其源码分析对于开发者进行二次开发具有重要的参考价值。本文将深入解析DSS的启动、初始化流程,以及核心模块的交互机制。 ...

    ThreadLocal源码分析和使用

    ThreadLocal 源码分析和使用 ThreadLocal 是 Java 语言中的一种多线程编程机制,用于解决多线程程序的并发问题。它不是一个 Thread,而是一个 Thread 的局部变量。ThreadLocal 的出现是为了解决多线程程序中的共享...

    java线程池的源码分析.zip

    本文将深入探讨Java线程池的源码分析,并对比不同类型的线程池,以帮助开发者更好地理解和利用这一强大的工具。 首先,我们要理解Java线程池的核心类`java.util.concurrent.ThreadPoolExecutor`,它是所有自定义...

    Java rt.jar 源码分析

    源码分析是提升Java开发者技能的重要途径,能够帮助我们理解Java内部的工作原理,优化代码,以及更好地调试和解决问题。 在这个主题“Java rt.jar 源码分析”中,我们将探讨以下几个关键知识点: 1. **Java标准库*...

    ARM 与RTOS Threadx操作系统源码

    通过深入学习和分析这些源码,开发者可以理解ThreadX如何在ARM上运行,如何管理任务、资源,以及如何与硬件交互。这对于优化系统性能、解决并发问题、调试错误以及设计高效的嵌入式系统都具有极大的价值。同时,这种...

    RT-Thread 1.1.0 Alpha源码

    **RT-Thread 1.1.0 Alpha源码详解** RT-Thread是一个开源、实时操作系统(RTOS),专为物联网设备和嵌入式系统设计。它提供了丰富的中间件服务,包括网络协议栈、文件系统、图形用户界面等,使得开发者能够方便地...

Global site tag (gtag.js) - Google Analytics