Java中Thread源码剖析

简介:                                        本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线程帮主线程完成一些任务。


                                       本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线程帮主线程完成一些任务。

线程的方法大部分都是使用Native使用,不允许应用层修改,是CPU调度的最基本单元。实现线程的方式有三种:使用内核线程、用户线程和混合线程来实现,奉行先行发生的原则。

内核线程:每个生成的线程,都1:1配比一个内核线程来支持,即双线程机制,消耗一个内核资源,类似手机中应用进程

用户线程:普通线程,高速且低耗,创建、切换、调度等问题都需要自己处理

混合实现:降低被阻塞的风险,用户线程与内核线程相当于M:N的关系

线程的调度方式主要有两种:协同式和抢占式,前者简单但不可控制,一个线程执行完通知另外一个;抢占式可以通过yield方法让出执行时间,Java目前就采用这种,同时可以使用设置优先级的方式来提前线程执行顺序,但有可能被“系统”关闭。


今天我们来看下线程的源码,进行系统的学习。

1、首先线程有六种状态

    public enum State {
        /**
         * The thread has been created, but has never been started.
         */
        NEW,
        /**
         * The thread may be run.
         */
        RUNNABLE,
        /**
         * The thread is blocked and waiting for a lock.
         */
        BLOCKED,
        /**
         * The thread is waiting.
         */
        WAITING,
        /**
         * The thread is waiting for a specified amount of time.
         */
        TIMED_WAITING,
        /**
         * The thread has been terminated.
         */
        TERMINATED
    }

NEW:刚创建还没启动

RUNNABLE:可以执行 

BLOCKED:堵塞状态,等待持有锁

WAITING :处理等待状态 

TIMED_WAITING:等待一些时间

TERMINATED:终止

    /**
     * The maximum priority value allowed for a thread.
     */
    public static final int MAX_PRIORITY = 10;


    /**
     * The minimum priority value allowed for a thread.
     */
    public static final int MIN_PRIORITY = 1;


    /**
     * The normal (default) priority value assigned to threads.
     */
    public static final int NORM_PRIORITY = 5;

2、分别是线程可设置的最大、最小和默认优先级,级别越高执行越靠前

    /**
     * Holds the thread's ID. We simply count upwards, so
     * each Thread has a unique ID.
     */
    private long id;

3、每个线程都有一个独一无二的ID

public Thread() {
        create(null, null, null, 0);
    }

 private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
        Thread currentThread = Thread.currentThread();
        if (group == null) {
            group = currentThread.getThreadGroup();
        }


        if (group.isDestroyed()) {
            throw new IllegalThreadStateException("Group already destroyed");
        }


        this.group = group;


        synchronized (Thread.class) {
            id = ++Thread.count;
        }


        if (threadName == null) {
            this.name = "Thread-" + id;
        } else {
            this.name = threadName;
        }


        this.target = runnable;
        this.stackSize = stackSize;


        this.priority = currentThread.getPriority();


        this.contextClassLoader = currentThread.contextClassLoader;


        // Transfer over InheritableThreadLocals.
        if (currentThread.inheritableValues != null) {
            inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
        }
        // add ourselves to our ThreadGroup of choice
        this.group.addThread(this);
    }

4、初始化一个空的线程,获得当前运行的线程群组,设置id,name,执行线程runnable,池大小stackSize,优先级,并加入到线程群组,这是一个无参的Thread,正常情况下应该有ThreadGroup、Runnable、threadName和stackSize这四个参数。一般threadName如果为空,则报出NullPointerException,stackSize默认为0。

    /**
     * Destroys the receiver without any monitor cleanup.
     *
     * @deprecated Not implemented.
     */
    @Deprecated
    public void destroy() {
        throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize???
    }

5、destroy方法在java7已经被抛弃。

    public void interrupt() {
        synchronized (interruptActions) {
            for (int i = interruptActions.size() - 1; i >= 0; i--) {
                interruptActions.get(i).run();
            }
        }

        VMThread vmt = this.vmThread;
        if (vmt != null) {
            vmt.interrupt();
        }
    }

6、停止当前线程,如果线程处于wait、join、sleep状态的线程,会报异常。

  public final boolean isAlive() {
        return (vmThread != null);
    }

7、线程是否死掉,主要是判断虚拟机线程有没有死掉VMThread,当然获得当前线程也是通过VMThread.currentThread(),以及接下下获得当前线程处于六大状态中的哪种。

    public State getState() {
        // TODO This is ugly and should be implemented better.
        VMThread vmt = this.vmThread;


        // Make sure we have a valid reference to an object. If native code
        // deletes the reference we won't run into a null reference later.
        VMThread thread = vmThread;
        if (thread != null) {
            // If the Thread Object became invalid or was not yet started,
            // getStatus() will return -1.
            int state = thread.getStatus();
            if(state != -1) {
                return VMThread.STATE_MAP[state];
            }
        }
        return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
    }

 public final void join() throws InterruptedException {
        VMThread t = vmThread;
        if (t == null) {
            return;
        }


        synchronized (t) {
            while (isAlive()) {
                t.wait();
            }
        }
    }

8、join堵塞当前线程,使其处于等待状态,因为子线程执行的时间可能比主线程执行时间还长,所以join是主线程需要在它执行完后再销毁。当然也可以加参数join(long millis, int nanos),使其等待N秒N毫秒,如果它已经处于join方法,则报InterruptedException 。

    public final void setDaemon(boolean isDaemon) {
        if (hasBeenStarted) {
            throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
        }


        if (vmThread == null) {
            daemon = isDaemon;
        }
    }

9、设置为守护线程,必须的runnable执行前设置,会在有非守护线程运行的时候执行,无则程序退出。

    public final void setPriority(int priority) {
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException("Priority out of range"); // TODO Externalize?
        }


        if (priority > group.getMaxPriority()) {
            priority = group.getMaxPriority();
        }


        this.priority = priority;


        VMThread vmt = this.vmThread;
        if (vmt != null) {
            vmt.setPriority(priority);
        }
    }

10、优先级主要通过VMThread来设置的,注意最高设为10最低为1,否则报 IllegalArgumentException。

   public static void sleep(long millis, int nanos) throws InterruptedException {

        VMThread.sleep(millis, nanos);
    }

11、执行sleep,如果在sleep期间被interrupt,会报InterruptedException。

    /**
     * Starts the new Thread of execution. The <code>run()</code> method of
     * the receiver will be called by the receiver Thread itself (and not the
     * Thread calling <code>start()</code>).
     *
     * @throws IllegalThreadStateException if the Thread has been started before
     *
     * @see Thread#run
     */
    public synchronized void start() {
        if (hasBeenStarted) {
            throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
        }


        hasBeenStarted = true;


        VMThread.create(this, stackSize);
    }

12、线程开始执行,如果start已经执行,则报IllegalThreadStateException

    @Deprecated
    public final synchronized void stop(Throwable throwable) {
        throw new UnsupportedOperationException();
    }

13、stop方法弃用

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

14、给另一个准备运行的线程让路,让它先执行

关于join和yield的区别,更在上一节: 

Java中join和yield的作用



目录
相关文章
|
1月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
45 7
|
21天前
|
Kubernetes jenkins 持续交付
从代码到k8s部署应有尽有系列-java源码之String详解
本文详细介绍了一个基于 `gitlab + jenkins + harbor + k8s` 的自动化部署环境搭建流程。其中,`gitlab` 用于代码托管和 CI,`jenkins` 负责 CD 发布,`harbor` 作为镜像仓库,而 `k8s` 则用于运行服务。文章具体介绍了每项工具的部署步骤,并提供了详细的配置信息和示例代码。此外,还特别指出中间件(如 MySQL、Redis 等)应部署在 K8s 之外,以确保服务稳定性和独立性。通过本文,读者可以学习如何在本地环境中搭建一套完整的自动化部署系统。
51 0
|
7天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
2天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
17天前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
|
30天前
|
Java
在 Java 中 Runnable 与 Thread 的适时运用
【8月更文挑战第22天】
18 0
|
1月前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
1月前
|
Java
Exception in thread "main" java.lang.UnsatisfiedLinkError: xxx()V
Exception in thread "main" java.lang.UnsatisfiedLinkError: xxx()V
10 0
|
1月前
|
存储 Java
【Java】Java学生成绩管理系统(源码+论文)【独一无二】
【Java】Java学生成绩管理系统(源码+论文)【独一无二】
|
1月前
|
SQL Java 数据库连接
【Java】Java Swing 图书管借阅管理系统(源码+论文)【独一无二】
【Java】Java Swing 图书管借阅管理系统(源码+论文)【独一无二】