阿里云Java 杂谈程序员

java线程

2018-08-28  本文已影响2人  良辰美景TT

  从操作系统的角度,可以简单认为,线程是系统调度的最小单元,一个进程可以包含多个线程,作为任务的真正运作者,有自己的栈(Stack)、寄存器(Register)、本地存储(Thread Local)等,但是会和进程内其他线程共享文件描述符、虚拟地址空间等。
  具体实现中,线程还分为内核线程、用户线程,Java 的线程实现其实是与虚拟机相关的。对于我们最熟悉的 Sun/Oracle JDK,其线程也经历了一个演进过程,基本上在 Java 1.2 之后,JDK 已经抛弃用户调度的线程,现在的模型是一对一映射到操作系统内核线程

线程的状态

  在 Java 5 以后,线程状态被明确定义在其公共内部枚举类型 java.lang.Thread.State 中,源代码如下:

    public enum State {
//新建状态
        NEW,
//就绪
        RUNNABLE,
//阻塞
        BLOCKED,

//等待
        WAITING,

//计时等待
        TIMED_WAITING,
//终止
        TERMINATED;
    }

各状态的具体含义如下:

其它知识

// 推荐
while ( isCondition()) {
waitForAConfition(...);
}

// 不推荐,可能引入 bug
if ( isCondition()) {
waitForAConfition(...);
}

比如线程里的join方法采用的就是上面的书写方式,源代码如下:

    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) {
//通过 while循环验证线程状态。
            while (isAlive()) {
//join内部是让被调用线程调用wait(0)操作来进行实现的
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class Test {

    public static void main(String[] args) throws Exception {
        
        System.out.println("hello");
        // 获取java的线程管理MXBean
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        // 不需要获取同步的monitor和synchronizer信息,仅获取线程和线程堆栈信息
        ThreadInfo[] threadInfo = threadBean.dumpAllThreads(false, false);
        // 遍历线程信息,仅打印线程id和线程名称信息
        for (ThreadInfo info : threadInfo) {
            System.out.println(info.getThreadId() + "--" + info.getThreadName() + "--" + info.getThreadState().name());
        }
        
    }
}

可以看出一个空的main方法会有如下几个线程:
1:main线程。
2:Reference Handler:处理引用对象本身的垃圾回收。
3:Finalizer:处理类的Finalizer方法。
4:Signal Dispatcher:外部jvm命令的转发器。
5:Attach Listener:负责接收外部命令的,如jmap、jstack。

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

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) { //默认b为空,不会进入这个方法
                interrupt0();           // Just to set the interrupt flag
//这里才会真正的中断线程
                b.interrupt(this);
                return;
            }
        }
        interrupt0(); //设置interrupt的状态并清除
    }
//属于Thread对象的方法
    public boolean isInterrupted() {
//传入的参数是false,不会清除Thread的interrupt状态
        return isInterrupted(false);
    }

//属于static方法
    public static boolean interrupted() {
//得到当前线程,并调用 isInterrupted, 传入的参数是true。会清除当前线程的interrupt状态 
        return currentThread().isInterrupted(true);
    }

//这是个本地方法
    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

上一篇下一篇

猜你喜欢

热点阅读