额外线程能力

线程组

使用ThreadGroup对象,你可以对其中有线程对象进行操作。假设一个线程组被变量tg引用,tg.susend();会暂停线程组内的所有线程。线程组简化了多条线程的管理工作。

建议不要使用该对象。

l  容易造成死锁

l  非线程安全

不过ThreadGroup对象处理异常有贡献,例如:

/**

 * Project Name:demo

 * File Name:ExceptionThread.java

 * Package Name:four

 * Date:2019年9月17日下午3:49:51

 * Copyright (c) 2019, 364574851@qq.com All Rights Reserved.

 *

*/

 

package four;

 

/**

 * ClassName:ExceptionThread <br/>

 * Function: TODO ADD FUNCTION. <br/>

 * Reason: TODO ADD REASON. <br/>

 * Date: 2019年9月17日 下午3:49:51 <br/>

 *

 * @author zhangxdp

 * @version

 * @since JDK 1.8

 * @see

 */

public class ExceptionThread {

 

         public ExceptionThread() {

 

                   // TODO Auto-generated constructor stub

 

         }

 

         @SuppressWarnings("static-access")

         public static void main(String[] args) {

                   Runnable r = new Runnable() {

 

                            @Override

                            public void run() {

                                     int x = 1 / 0;

                            }

                   };

 

                   Thread t = new Thread(r);

 

                   Thread.UncaughtExceptionHandler uceh;

 

                   uceh = new Thread.UncaughtExceptionHandler() {

 

                            @Override

                            public void uncaughtException(Thread t, Throwable e) {

 

                                     // TODO Auto-generated method stub

                                     System.out.println("Caught throwable" + e + "for Thread " + t);

 

                            }

                   };

 

                   t.setUncaughtExceptionHandler(uceh);

 

                   uceh = new Thread.UncaughtExceptionHandler() {

 

                            @Override

                            public void uncaughtException(Thread t, Throwable e) {

 

                                     // TODO Auto-generated method stubo

                                     System.out.println("Default uncaught exception handler");

                                     System.out.println("Caught throwable" + e + "for Thread " + t);

 

                            }

                   };

                   t.setDefaultUncaughtExceptionHandler(uceh);

                   t.start();

                   System.out.println("11");

         }

 

}

 

打印输出:

11

Caught throwablejava.lang.ArithmeticException: / by zerofor Thread Thread[Thread-0,5,main]

 

默认的处理器并未被调用,看不到他的。想要看到输出,注释掉t.setUncaughtExceptionHandler(uceh);即可。

 

线程局部变量

ThreadLocal 创建一个线程局部变量,为每个线程准备局部变量槽来存放信息,彼此独立,相互不影响。

l  ThreadLocal()创建一个新的线程局部变量

l  T get(): 返回 调用线程的存储槽中的值。如果当这个线程调用此方法值不存在时,那么get()会调用initialValue()方法

l  initialValue() : 创建调用线程的存储槽并存入一个初始值。默认初始值为null。你必须继承类ThreadLocal 来重写protected 方法 来提供一个更合适的初始值。

l  void remove() : 清空调用线程的存储槽。

l  void set(): 设置存储槽中的值

public class ThreadLocalDemo {

   private static volatile ThreadLocal<String> userId = new ThreadLocal<>();

 

   public static void main(String[] args) {

      Runnable r = new Runnable() {

 

        @Override

        public void run() {

           String name = Thread.currentThread().getName();

           if ("A".equals(name)) {

              userId.set("foxtrot");

           } else {

              userId.set("zhang3");

           }

 

           System.out.println(name + "   " + userId.get());

        }

      };

 

      Thread t1 = new Thread(r);

      t1.setName("A");

 

      Thread t2 = new Thread(r);

      t2.setName("B");

 

      t1.start();

      t2.start();

   }

}

 

InheritableThreadLocal : ThreadLocal的子类。 完成线程槽,从父线程传递子线程。

l  T childValue(T prarentValue) : 在子线程被创建出来的时候,用父线程的值计算出子线程的初始值。此方法会在子线程启动之前被父线程调用。

   public static void main(String[] args) {

      Runnable rp = () -> {

        intVal.set(new Integer(10));

        Runnable rc = () -> {

           Thread thd = Thread.currentThread();

           String name = thd.getName();

           System.out.printf("%s  %d%n", name, intVal.get());

        };

        Thread thdChild = new Thread(rc);

        thdChild.setName("child");

        thdChild.start();

      };

      new Thread(rp).start();

   };

 

输出结果:

child  null

 

说明ThreadLocal 不行

 

 

   private static final InheritableThreadLocal<Integer> intVal = new InheritableThreadLocal<>();

 

   public static void main(String[] args) {

      Runnable rp = () -> {

        intVal.set(new Integer(10));

        Runnable rc = () -> {

           Thread thd = Thread.currentThread();

           String name = thd.getName();

           System.out.printf("%s  %d%n", name, intVal.get());

        };

        Thread thdChild = new Thread(rc);

        thdChild.setName("child");

        thdChild.start();

      };

      new Thread(rp).start();

   };

输出结果:

child  10

定时器框架

First 定时任务

   public static void main(String[] args) {

      TimerTask tt = new TimerTask() {

 

        @Override

        public void run() {

           System.out.println("alarm goring off");

           System.exit(0);

        }

      };

 

      Timer t = new Timer();

      t.schedule(tt, 2000);

   }

 

以固定时长间隔重复执行定时器任务。

      TimerTask tt = new TimerTask() {

 

        @Override

        public void run() {

 

           // TODO Auto-generated method stub

           System.out.println("hello word" + "   " + System.currentTimeMillis());

        }

      };

 

      Timer t = new Timer();

      t.schedule(tt, 0, 1000);

   }

 

输出结果:

hello word   1569205436012

hello word   1569205437012

hello word   1569205438012

hello word   1569205439012

hello word   1569205440012

hello word   1569205441012

深入Timer

l  Timer() : 创建一个新的非守护线程的定时器。

l  Timer(boolean isDaemon) : 创建一个是否守护线程的电器还是任务。

l  Timer(String name) : 创建一个有名字的定时器。如果name=null, 会抛出异常NullPointException

l  Timer(Sring name , Boolean isDaemon) 一个有名字的是否守护线程的定时器。

l  Void cancel(): 终止该定时器,丢弃所有当前调度的定时器任务。注意不会影响前面正在执行的任务。

l  Int purge() : 从该定时器队列中移除所有取消的定时任务,并返回被移植的任务数目。 该方法一般不使用。

l  Void schedule(TimerTask task , Date time): 在某个时间执行定时任务.

l  Viud schedule(TimerTask task,Date firstTime , long period ) : 调用任务与firstTime开始,以固定时间perviod间隔重复执行定时任务。

l  Void  schedule(TimerTask task , long time): 在time 毫秒数之后,执行任务。

l  Viud schedule(TimerTask task,long firstTime , long period):在firstTime毫秒数后,间毫秒数period重复执行。

当最后一条指向Timer对象的引用消失并且所有重要的定时任务执行后,该定时器会优雅的结束,并且被垃圾回收。

深入TimerTask

定时任务都是抽象类TimerTast子类的实例。可以在重写的run()方法调用以下方法:

l  Boolean cancle() : 取消这个定时任务。

l  Long scheduleExecutionTime() : 返回次定时任务最近时间被调用的执行时间。

 

posted on 2019-09-23 10:37  不在是从前  阅读(71)  评论(0)    收藏  举报

导航