Thread机制与源码分析

线程定义

线程是现代操作系统调度的最小单元,一个进程可以创建多个线程来提高系统的吞吐量和执行效率。

:进程是操作系统资源分配和调度的基本单位,它可以创建多个线程,进程可创建的线程数量跟操作系统相关。

为什么要使用多线程?

  • 更多的处理器核心;
  • 更快的响应时间;
  • 更好的编程模型:java提供了一套完整的jmm规则,屏蔽了底层的一些操作,开发人员只需要关注自己的业务逻辑即可。

线程的状态

  • NEW:初始状态,线程被构建,还未调用start()方法;
  • RUNNABLE:运行状态,在java多线程模型中,就绪和运行都是运行状态;
  • BLOCKED:阻塞状态;
  • WAITING:等待状态,比如中断,需要其他的线程来唤醒;
  • TIME_WAITING:超时等待,可以在指定的时间内自行返回;
  • TERMINATED:终止状态,线程执行完毕。

Thread源码分析

  • 构造线程

构造函数:

//无参构造方法
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

//带参构造方法
public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

public Thread(ThreadGroup group, Runnable target) {
    init(group, target, "Thread-" + nextThreadNum(), 0);
}

public Thread(String name) {
    init(null, null, name, 0);
}

public Thread(ThreadGroup group, String name) {
    init(group, null, name, 0);
}

public Thread(Runnable target, String name) {
    init(null, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
    init(group, target, name, stackSize);
}

所有的构造方法都调用了init这个方法,接下来我们就来详细的看看init方法到底是怎么来初始化线程的。

初始化线程:

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
    //参数校验,线程name不能为null
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }
    this.name = name.toCharArray();
    //当前线程就是该线程的父线程
    Thread parent = currentThread();
    //获取系统的security
    SecurityManager security = System.getSecurityManager();
    if (g == null) {
        //security不为null时,线程所在group为security的group
        if (security != null) {
            g = security.getThreadGroup();
        }
        //security为null时,直接使用父线程的group
        if (g == null) {
            g = parent.getThreadGroup();
        }
    }
    g.checkAccess();

    //授权
    if (security != null) {
        if (isCCLOverridden(getClass())) {            security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
        }
    }
    g.addUnstarted();
    this.group = g;
    //将守护线程、优先级等设置为父线程的对应属性
    this.daemon = parent.isDaemon();
    this.priority = parent.getPriority();
    if (security == null || isCCLOverridden(parent.getClass()))
        this.contextClassLoader = parent.getContextClassLoader();
    else
        this.contextClassLoader = parent.contextClassLoader;
    this.inheritedAccessControlContext =
            acc != null ? acc : AccessController.getContext();
    this.target = target;
    setPriority(priority);
    if (parent.inheritableThreadLocals != null)
        //创建线程共享变量副本
        this.inheritableThreadLocals =         ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    this.stackSize = stackSize;
    //分配线程id
    tid = nextThreadID();
}

  • 启动线程
public synchronized void start() {
    //假若当前线程初始化还未做好,不能start,0->NEW状态
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    //通知group该线程即将启动,group的未启动线程数量减1
    group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            //启动不成功,group设置当前线程启动失败
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {

        }
    }
}

启动线程其实做了这么几件事:

  1. 检查线程是否初始化;
  2. 通知group,线程启动;
  3. 调用native方法start0()启动线程,启动后执行run()方法;
  4. 启动失败容错处理。

  • 线程中断
    中断可以理解为一个标识位的属性,它标识一个运行中的线程是否被其他线程进行了中断操作。

中断线程:

public void interrupt() {
    //中断其他线程,需要先判断当前线程是否允许修改其他线程
    if (this != Thread.currentThread())
        checkAccess();
    //中断该线程
    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();//设置中断标识位
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}

查看当前线程是否被中断:

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

查看线程是否被中断,已中断返回false

public boolean isInterrupted() {
    return isInterrupted(false);
}

  • 线程的暂停、恢复和停止

: 这几个操作都加有@Deprecated注解,不推荐程序员使用

暂停:

//可能会造成死锁
@Deprecated
public final void suspend() {
    checkAccess();
    suspend0();
}

恢复:

//可能会造成死锁
@Deprecated
public final void resume() {
    checkAccess();
    resume0();
}

停止:

@Deprecated
public final synchronized void stop(Throwable obj) {
    if (obj == null)
        throw new NullPointerException();

    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        checkAccess();
        if ((this != Thread.currentThread()) ||
            (!(obj instanceof ThreadDeath))) {
            security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
        }
    }
    //线程还未初始化好,暂停该线程
    if (threadStatus != 0) {
        resume(); 
    }

    //jvm处理线程相关内容
    stop0(obj);
}

  • 线程优先级设置
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);
    }
}

需要注意的是:线程优先级不能作为程序正确性的依赖,操作系统有线程优先级的设定,不以程序设定的优先级为准!

你可能感兴趣的:(Thread机制与源码分析)