简单了解ava线程Thread

      之前的文章中,提到了线程的一个关键方法join,以及Thread的线程状态,这些都是Thread代码中的内容,今天,我们再来看一看Thread。

      Thread这个类,可以说是JDK中最重要的类之一,只要你用到了异步、锁、等待等都离不开Thread的身影,哪怕你启动一个main方法,后台也是要用到Thread这个类的。想要了解这个类,还是要从它的构造方法开始。我们来看下Thread的构造方法。

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

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

 /*ThreadGroup ,Runnable入参构造方法*/
 public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }

 /*线程名称入参构造方法*/
 public Thread(String name) {
        init(null, null, name, 0);
    }
/*ThreadGroup ,线程名称入参构造方法*/
 public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

/*Runnable ,线程名称入参构造方法*/
 public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
/*ThreadGroup ,Runnable ,线程名称入参构造方法*/
public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }

/*ThreadGroup ,Runnable ,线程名称,预期堆栈大小 入参构造方法*/
public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        init(group, target, name, stackSize);
    }

       Thread的构造方法有很多,但是大家可以发现,所有的构造方法都是指向了init方法,Thread的构造方法其实也就是通过init方法来实现的!一般来说,在构造方法中处理逻辑是不太建议的,当然,如果你比较精通这方面,也是可以这么操作的,^_^。

       我们来看下init方法。方法里涉及到很多东西,比如权限,线程组,执行的先后顺序,甚至线程占有多大内存都有设置,不过对我们来说,一般用到的就三个线程名称,线程id,以及线程执行的target(Runnable)再加上线程的状态 (*^▽^*)

 // Thread 初始化方法
 private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
		// 线程命名,线程必须有名字
        this.name = name;

        Thread parent = currentThread();
		//SecurityManager是一个允许应用实现一种安全策略的类,它允许一个应用去明确,在执行一个可能
		//安全或者敏感的操作之前,此操作是否允许在一个安全的上下文中执行。应用可以统一或者拒绝执行
		//操作。
        SecurityManager security = System.getSecurityManager();
		//线程组为空
        if (g == null) {
            //管理策略不为空,就是去从security中获取当前线程的线程组
            if (security != null) {
                g = security.getThreadGroup();
            }
			// security没有赋值group,那么久直接使用parent的ThreadGroup
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        //判断线程组是否允许操作(这个源码有点多,就不深入了)
        g.checkAccess();

        /*
         * security 不为空的话,检验Class的管理策略
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

		//把线程加入到ThreadGroup组里。
        g.addUnstarted();
		//线程组
        this.group = g;
		//是否是守护线程
        this.daemon = parent.isDaemon();
		//优先级,默认是5,数字越大越先执行,从0开始
        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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //给线程分配的栈大小,这个一般是默认的
        this.stackSize = stackSize;

        //线程ID
        tid = nextThreadID();
    }

这是init方法的一些解释,具体就不深入了,里面的东西牵涉的比较多。下面展示下Thread的属性吧,方便大家尽快熟悉线程。

//线程名字
private volatile String name;
//优先级
private int            priority;
// 内置的一个线程Thread类
private Thread         threadQ;
//JVM中的JavaThread指针
private long           eetop;

// 是否单步执行此线程 
private boolean     single_step;

// 是否是守护线程 
private boolean     daemon = false;

// 虚拟机状态 
private boolean     stillborn = false;

// 传进来的对象 
private Runnable target;

// 线程的组 
private ThreadGroup group;

// 线程的上下文加载器,可以用来加载一些资源 
private ClassLoader contextClassLoader;

// 继承的访问控制上下文 
private AccessControlContext inheritedAccessControlContext;

// 给匿名线程命名的整数,匿名线程会被命名为Thread-1这类名字,这个int会自增 
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}

//ThreadLocal的Map用于保存变量副本,不了解的话可以看下之前关于ThreadLocal的讲解 
ThreadLocal.ThreadLocalMap threadLocals = null;

// InheritableThreadLocal用于子线程能够拿到父线程往ThreadLocal里设置的值 
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

//给线程分配的栈大小
private long stackSize;

// 本地线程终止之后的专用状态
private long nativeParkEventPointer;

// 线程ID
private long tid;

// 用于生成线程ID 
private static long threadSeqNumber;

// 线程状态 
private volatile int threadStatus = 0;

下面主要就是join和线程的状态了,其他许多都是native方法,不太好分析。

        这里我再说下join,我们可以看到join方法。

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

    }

       是使用synchronized修饰的,所以一旦有线程(thread1)调用join方法,相当于join方法就获取到了监视器锁,这个锁内部的逻辑没有执行完,主方法的逻辑是无法执行的,这个就是join方法能提前运行的。

  while (isAlive()) {
                wait(0);
            }

可以看到,join方法中有wait方法,那么既然有wait方法最终执行完肯定是要唤醒做唤醒操作的,毕竟thread1是在主线程中运行的,不能thread1运行完了,啥都不管了,然后就把主线程撂那了,那主线程要骂N了。这里copy下大佬的带讲解

//一个c++函数:
void JavaThread::exit(bool destroy_vm, ExitType exit_type) ;

//这家伙是啥,就是一个线程执行完毕之后,jvm会做的事,做清理啊收尾工作,
//里面有一个贼不起眼的一行代码,眼神不好还看不到的呢,就是这个:

ensure_join(this);

//翻译成中文叫 确保_join(这个);代码如下:

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());

  ObjectLocker lock(threadObj, thread);

  thread->clear_pending_exception();

  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

  java_lang_Thread::set_thread(threadObj(), NULL);

  //同志们看到了没,别的不用看,就看这一句,
//thread就是当前线程
  lock.notify_all(thread);

  thread->clear_pending_exception();
}

// 链接:https://www.zhihu.com/question/44621343/answer/97640972

       这里可以看到在JVM源码中有对线程的唤醒操作,就是thread1执行完了,肯定是要notifyAll一下的,然后唤醒主线程,不然逻辑就卡那了,O(∩_∩)O哈哈~

No sacrifice ,no victory~

猜你喜欢

转载自blog.csdn.net/zsah2011/article/details/109479249