zoukankan      html  css  js  c++  java
  • 多线程之线程初始

                                                                         多线程之线程初始
      上章我们讲了线程的概念,这章我们来深入的了解下一个线程整个初始的过程,感谢上次小伙伴们的意见,后面我都会是文字+图片+代码。让大家看的更轻松。
            创建一个线程的代码为:

          Thread t = new Thread();
        但这仅仅仅仅是初始了一个线程(它眼下还什么都不知道仅仅是静静的“坐”在一边),我们来看看这个初始中详细做了哪些事情:
      public Thread() {
     init(null, null, "Thread-" + nextThreadNum(), 0);
        }

      能够看到创建线程就是调用了一个初始的方法,再看看每一个參数的解释:
        1  param g the Thread group
        2  param target the object whose run() method gets called
        3 param name the name of the new Thread
        4  param stackSize the desired stack size for the new thread, or
        zero to indicate that this parameter is to be ignored.
    第一个參数就是一个线程组,他的作用就是来方便对线程的统一管理,每个线程都要归属于一个线程组,假设我们不去明白的制定。那么就归属到默认线程组,当然无论是哪个线程组终于都归属于系统线程组,若创建多个线程而不指定一个组,它们就会自己主动归属于系统线程组。

    第2个參数是调用run()方法的对象,也就是任务对象本身。

    第3个创建线程的名称。

    第4个就是堆栈的默认分配空间(默认值是0)


    JDK中重载了非常多创建线程的方法,可是详细实现的过程是大同小异:
    private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize) {
     Thread parent = currentThread();
     SecurityManager security = System.getSecurityManager();
     if (g == null) {
         /* Determine if it's an applet or not */
         
         /* If there is a security manager, ask the security manager
            what to do. */
         if (security != null) {
      g = security.getThreadGroup();
         }
         /* If the security doesn't have a strong opinion of the matter
            use the parent thread group. */
         if (g == null) {
      g = parent.getThreadGroup();
         }
     }
     /* checkAccess regardless of whether or not threadgroup is
               explicitly passed in. */
     g.checkAccess();
     /*
      * Do we have the required permissions?

      */
     if (security != null) {
         if (isCCLOverridden(getClass())) {
             security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
         }
     }
            g.addUnstarted();
     this.group = g;
     this.daemon = parent.isDaemon();
     this.priority = parent.getPriority();
     this.name = name.toCharArray();
     if (security == null || isCCLOverridden(parent.getClass()))
         this.contextClassLoader = parent.getContextClassLoader();
     else
         this.contextClassLoader = parent.contextClassLoader;
     this.inheritedAccessControlContext = AccessController.getContext();
     this.target = target;
     setPriority(priority);
            if (parent.inheritableThreadLocals != null)
         this.inheritableThreadLocals =
      ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
            /* Stash the specified stack size in case the VM cares */
            this.stackSize = stackSize;
            /* Set thread ID */
            tid = nextThreadID();
        }

    首先会拿到当前线程的对象的引用。然后分配一个线程组(默认线程组选择权最低,參数的选择权最高),然后就是一系列给属性赋值的操作。这里就不细说了,当中有一些重要的属性来说明下:

       /* Whether or not to single_step this thread. */
        private boolean single_step;
        是否为一个简单的线程


    /* Whether or not the thread is a daemon thread. */
        private boolean daemon = false;
      是否是后台线程。 Daemon的作用是为其它线程的执行提供服务,比方说GC线程。

    事实上User Thread线程和Daemon Thread守护线程本质上来说去没啥差别的,唯一的差别之处就在虚拟机的离开:假设User Thread所有撤离。那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。


    /* JVM state */
        private boolean stillborn = false;

    是否为激活状态。对于线程的状态我们后面会具体的介绍


     /* What will be run. */
        private Runnable target;
       任务实体类对象,详细任务放在继续Runnable接口的run()方法中


        /* The group of this thread */
        private ThreadGroup group;
    线程组


      /* The context ClassLoader for this thread */
        private ClassLoader contextClassLoader;
    线程上下文的载入器



     /* The inherited AccessControlContext of this thread */
        private AccessControlContext inheritedAccessControlContext;
    这里是继承AccessControlContext类()这里才是真正的线程,而等到线程的方法就是:
    this.inheritedAccessControlContext = AccessController.getContext();
    事实上这里是用一种调用当前上下文的快照的技术。而我们通常使用的dubug对象也是在AccessController类中,代码:
    public final class AccessControlContext {
        private ProtectionDomain context[];
        private boolean isPrivileged;
        private AccessControlContext privilegedContext;
        private DomainCombiner combiner = null;
        private static boolean debugInit = false;
        private static Debug debug = null;
        static Debug getDebug()
        {
     if (debugInit)
         return debug;
     else {
         if (Policy.isSet()) {
      debug = Debug.getInstance("access");
      debugInit = true;
         }
         return debug;
     }
        }



    /* For autonumbering anonymous threads. */
        private static int threadInitNumber;
    这里就是为线程id命名的一个id(是线程id组成的一部分。线程id的结构是“Thread-”+threadInitNumber),这id也是自增的,代码:

     private static synchronized int nextThreadNum() {
     return threadInitNumber++;
        }

    而在线程初始的时候就给了id,代码:
     tid = nextThreadID();


     private long stackSize;
    堆栈空间,默认jvm会分配

     private long tid;
    线程id


    /* Java thread status for tools,
         * initialized to indicate thread 'not yet started'
         */
        private int threadStatus = 0;
    线程状态。可惜的是没备注全部的状态解释和相应的状态值


    /**
         * The minimum priority that a thread can have.
         */
        public final static int MIN_PRIORITY = 1;
    最小线程的优先权
       /**
         * The default priority that is assigned to a thread.
         */
        public final static int NORM_PRIORITY = 5;
    默认线程的优先权
        /**
         * The maximum priority that a thread can have.
         */
        public final static int MAX_PRIORITY = 10;
     最大线程的优先权


    大致就这些吧,以上是线程中比較重要线程的属性。这会有助于我们跟好的去理解线程的组成和机制

    事实上以上只不过说明了线程在jdk层的初始,但从一台电脑来讲,整个线程创建的流程是如何了?
    大家都知道在java层调度操作系统时中间另一层jvm。这里本人也没去深究jvm和操作系统之间的通讯,但大致画出了一个创建线程的流程图:

    在我们工作中我们实际还是从线程池中去拿。而这又涉及到对线程池工作原理的了解,但在这章我们不做解说。

    (从jdk的层面讲)


    总之这一章主要是希望让大家明确线程究竟有哪些熟悉。怎样初始。
  • 相关阅读:
    LinQ Group By
    sql server 还原数据库后,删除用户,提示数据库主体在该数据库中拥有架构,无法删除解决方法
    各种网站资源
    Easyui TreeGrid数据源
    MVC中创建自定义视图的t4模板
    栈溢出练习
    Stack Canary
    攻防世界pwn之新手练习区
    开源 PetaPoco 扩展~一个小型轻巧的ORM~
    linux调度全景指南
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6890771.html
Copyright © 2011-2022 走看看