读书笔记《JAVA并发编程的艺术》 第四章 Java并发编程基础 4.2 启动和终止线程

4.2 启动和终止线程

4.2.1 构造线程

JDK1.8中java.lang.Thread类中的init方法源码:

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc) {
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }

    this.name = name.toCharArray();
    //当前线程是该线程的父线程
    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;
    //将daemon、priority属性设置为父线程的对应属性
    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);
    // 继承父线程的inheritableThreadLocals 
    if (parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;

    /* 分配一个线程ID */
    tid = nextThreadID();
}

4.2.3 理解中断

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

  1. isInterrupted:判断一个线程是否被中断,如果一个线程已经处于终结状态,即使之前这个线程被中断过,此时此刻调用该对象的isInterrupted方法返回的也是false.
  2. Thread.interrupted():对当前线程的中断标识位进行复位。

        /**
        * Tests whether the current thread has been interrupted.  The
        * * <i>interrupted status</i> of the thread is cleared by this method.  In
         * other words, if this method were to be called twice in succession, the
         * second call would return false (unless the current thread were
         * interrupted again, after the first call had cleared its interrupted
         * status and before the second call had examined it).
         *
         * <p>A thread interruption ignored because a thread was not alive
         * at the time of the interrupt will be reflected by this method
         * returning false.
         *
         * @return  <code>true</code> if the current thread has been interrupted;
         *          <code>false</code> otherwise.
         * @see #isInterrupted()
         * @revised 6.0
         */
         // 验证当前线程是否被中断过。对当前线程的中断标识位进行复位。换句话说,如果连续两次调用该方法,第二次调用时会返回false(除非是调用第一次后,调用第二次之前的时间空挡内又被中断过,会返回true)
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
    

4.2.4 过期的suspend()、resume()和stop()

4.2.5 安全的终止线程

    public class ShutDown{
        private static class Runner implements Runnable{
            private long i;
            private volatile boolean on = true;
            @Override
            public void run(){
                while(on && !Thread.currentThread().isInterrupted()){
                    i++;
                }
                System.out.println("Count i = " + i);
            }
            public void cancle(){
                on = false;
            }
        }

        public static void main(String[] args)throws Exception{
            Runner one = new Runner();
            Thread countThread = new Thread(one,"CountThread");
            countThread.start();
            //睡眠1秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束
            TimeUnit.SECONDES.sleep(1);
            countThread.interrupt();
            Runner two = new Runner();
            countThread = new Thread(two,"CountThread");
            countThread.start();
            //睡眠1秒,main线程对Runner two 进行取消,使CountThread能够感知on为false而结束
            TimeUnit.SECONDS.sleep(1);
            two.cancel();
        }
    }


 输出结果如下所示,可能会有所不同:
 Count i = 543487324
 Count i = 540898082

总结:main线程可以通过中断操作和cancel()方法均可使CountThread得以终止。

猜你喜欢

转载自blog.csdn.net/maohoo/article/details/81296253