额外线程能力
线程组
使用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() : 返回次定时任务最近时间被调用的执行时间。
浙公网安备 33010602011771号