【java多线程编程核心技术】7.拾遗增补-笔记总结
来源:互联网 发布:淘宝福袋真的不能退吗 编辑:程序博客网 时间:2024/05/16 01:49
线程的状态
线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中
这些状态之间某些是可双向切换的,比如waiting和running状态之间可以循环地进行切换
有些事单向切换的,比如线程销毁后并不能自动进入Running状态
线程组
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程。
线程组作用:批量管理线程或线程组对象,有效地对线程或线程组对象进行组织
线程对象管理线程组:1级关联
1级关联:父对象中有子对象,但不创建子孙对象。
package test;import extthread.ThreadA;import extthread.ThreadB;public class Run { public static void main(String[] args) { ThreadA aRunnable = new ThreadA(); ThreadB bRunnable = new ThreadB(); ThreadGroup group = new ThreadGroup("高洪岩的线程组"); Thread aThread = new Thread(group, aRunnable); //将 aThread线程归属到group线程组中 Thread bThread = new Thread(group, bRunnable); aThread.start(); bThread.start(); System.out.println("活动的线程数为:" + group.activeCount()); System.out.println("线程组的名称为:" + group.getName()); }}
Thread aThread = new Thread(group, aRunnable); //将 aThread线程归属到group线程组中
线程对象管理线程组:多级关联
多级关联:父对象中有子对象,子对象中再创建子对象,也就是出现子孙对象的效果。(代码知识点后面章节会覆盖)
线程组自动归属特性
public class Run { public static void main(String[] args) { System.out.println("A处线程:"+Thread.currentThread().getName()+" 中有线程组数量:"+Thread.currentThread().getThreadGroup().activeGroupCount()); ThreadGroup group=new ThreadGroup("新的组"); System.out.println("A处线程:"+Thread.currentThread().getName()+" 中有线程组数量:"+Thread.currentThread().getThreadGroup().activeGroupCount()); ThreadGroup[] threadGroup=new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()]; Thread.currentThread().getThreadGroup().enumerate(threadGroup); for (int i = 0; i < threadGroup.length; i++) { System.out.println("第一个线程组名称为:"+threadGroup[i].getName()); } }}输出结果:A处线程:main 中有线程组数量:0A处线程:main 中有线程组数量:1第一个线程组名称为:新的组
activeGroupCount():取得当前线程组对象中的子线程组数量
enumerate():将线程组中的子线程组以复制的形式拷贝到ThreadGroup[]数组对象中
在实例化一个ThreadGroup线程组x时,如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中。
获取根线程组
Thread.currentThread().getThreadGroup().getParent() //输出:systemThread.currentThread().getThreadGroup().getPatent().getParent().getParent() //报空指针异常
JVM的根线程组就是system,再取其父线程组则出现空异常
线程组里加线程组
ThreadGroup newGroup = new ThreadGroup(Thread.currentThread() .getThreadGroup(), "newGroup");
显式的方式在一个线程组(此处为main线程组)中添加一个名称为“newGroup”子线程组
组内的线程批量停止
ThreadGroup group = new ThreadGroup("我的线程组"); for (int i = 0; i < 5; i++) { MyThread thread = new MyThread(group, "线程" + (i + 1)); thread.start(); } Thread.sleep(5000); group.interrupt(); System.out.println("调用了interrupt()方法");
线程组中所有的线程均处于被调用interrupt()方法的状态中,批量执行。
递归与非递归取得组内对象
Thread.currentThread().getThreadGroup().enumerate(listGroup1, true); //递归 Thread.currentThread().getThreadGroup().enumerate(listGroup2, false);//非递归
递归取得组内对象:复制子线程组及其子孙线程组
非递归取得组内对象:只复制子线程组
SimpleDateFormat非线程安全
类SimpleDateFormat主要负责日期的转换与格式化,SimpleDateFormat类在多线程环境中,容易造成数据转换及处理的不准确,因为SimpleDateFormat类并不是线程安全的
解决异常方法:通过ThreadLocal类解决
ThreadLocal类详解:http://blog.csdn.net/yangdongchuan1995/article/details/78578337
package extthread;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import tools.DateTools;public class MyThread extends Thread { private SimpleDateFormat sdf; private String dateString; public MyThread(SimpleDateFormat sdf, String dateString) { super(); this.sdf = sdf; this.dateString = dateString; } @Override public void run() { try { Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse( dateString); String newDateString = DateTools.getSimpleDateFormat("yyyy-MM-dd") .format(dateRef).toString(); if (!newDateString.equals(dateString)) { System.out.println("ThreadName=" + this.getName() + "报错了 日期字符串:" + dateString + " 转换成的日期为:" + newDateString); } } catch (ParseException e) { e.printStackTrace(); } }}package tools;import java.text.SimpleDateFormat;public class DateTools { private static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>(); public static SimpleDateFormat getSimpleDateFormat(String datePattern) { SimpleDateFormat sdf = null; sdf = tl.get(); if (sdf == null) { sdf = new SimpleDateFormat(datePattern); tl.set(sdf); } return sdf; }}package test.run;import java.text.SimpleDateFormat;import extthread.MyThread;public class Test { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String[] dateStringArray = new String[] { "2000-01-01", "2000-01-02", "2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06", "2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10" }; MyThread[] threadArray = new MyThread[10]; for (int i = 0; i < 10; i++) { threadArray[i] = new MyThread(sdf, dateStringArray[i]); } for (int i = 0; i < 10; i++) { threadArray[i].start(); } }}输出结果:(什么都不输出,因为没报错)
线程中出现异常的处理
package controller;import java.lang.Thread.UncaughtExceptionHandler;import extthread.MyThread;public class Main2 { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.setName("线程t1"); t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("线程:" + t.getName() + " 出现了异常:"); e.printStackTrace(); } });// MyThread// .setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {// @Override// public void uncaughtException(Thread t, Throwable e) {// System.out.println("线程:" + t.getName() + " 出现了异常:");// e.printStackTrace();//// }// }); t1.start(); MyThread t2 = new MyThread(); t2.setName("线程t2"); t2.start(); }}
setUncaughtExceptionHandler():对指定的线程对象设置默认的异常处理器
setDefaultUncaughtExceptionHandler():为指定线程类的所有线程对象设置默认的异常处理器
线程组内处理异常
package extthread;public class MyThread extends Thread { private String num; public MyThread(ThreadGroup group, String name, String num) { super(group, name); this.num = num; } @Override public void run() { int numInt = Integer.parseInt(num); while (this.isInterrupted() == false) { System.out.println("死循环中:" + Thread.currentThread().getName()); } }}package extthreadgroup;public class MyThreadGroup extends ThreadGroup { public MyThreadGroup(String name) { super(name); } @Override public void uncaughtException(Thread t, Throwable e) { super.uncaughtException(t, e); this.interrupt(); }}package test.run;import extthread.MyThread;import extthreadgroup.MyThreadGroup;public class Run { public static void main(String[] args) { MyThreadGroup group = new MyThreadGroup("我的线程组"); MyThread[] myThread = new MyThread[3]; for (int i = 0; i < myThread.length; i++) { myThread[i] = new MyThread(group, "线程" + (i + 1), "1"); myThread[i].start(); } MyThread newT = new MyThread(group, "报错线程", "a"); newT.start(); }}输出结果:死循环中:线程1死循环中:线程1死循环中:线程1死循环中:线程1死循环中:线程1死循环中:线程1死循环中:线程2死循环中:线程3死循环中:线程3死循环中:线程3死循环中:线程3java.lang.NumberFormatException: For input string: "a" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.parseInt(Integer.java:527) at extthread.MyThread.run(MyThread.java:14)
重现uncaughtException方法处理组内线程中断行为时,每个线程对象中的run()方法内部不要有异常catch语句
线程异常处理的传递
public static void main(String[] args) { MyThread myThread = new MyThread(); // 对象 myThread .setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler()); // 类 MyThread .setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler()); myThread.start(); }
在未设置线程组时,setUncaughtExceptionHandler()先捕获异常,在前者未配置的情况下,才让setDefaultUncaughtExceptionHandler()进行捕获异常。
package extthread;public class MyThread extends Thread { private String num = "a"; public MyThread() { super(); } public MyThread(ThreadGroup group, String name) { super(group, name); } @Override public void run() { int numInt = Integer.parseInt(num); System.out.println("在线程中打印:" + (numInt + 1)); }}package extthreadgroup;public class MyThreadGroup extends ThreadGroup { public MyThreadGroup(String name) { super(name); } @Override public void uncaughtException(Thread t, Throwable e) {// super.uncaughtException(t, e); System.out.println("线程组的异常处理"); e.printStackTrace(); }}package test.extUncaughtExceptionHandler;import java.lang.Thread.UncaughtExceptionHandler;public class ObjectUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("对象的异常处理"); e.printStackTrace(); }}package test.extUncaughtExceptionHandler;import java.lang.Thread.UncaughtExceptionHandler;public class StateUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("静态的异常处理"); e.printStackTrace(); }} public static void main(String[] args) { MyThreadGroup group = new MyThreadGroup("我的线程组"); MyThread myThread = new MyThread(group, "我的线程"); // 对象 myThread .setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler()); // 类 MyThread .setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler()); myThread.start(); }
在设置了线程组以后,也同样是setUncaughtExceptionHandler()先捕获异常,
再者是线程组的异常处理
将//super.uncaughtException(t, e); 注释取消后, 线程组的异常处理与静态的异常处理 能一起输出。
- 【java多线程编程核心技术】7.拾遗增补-笔记总结
- Java多线程编程核心技术---拾遗增补
- java多线程编程核心技术7-拾遗增补
- Java多线程编程7--拾遗增补--线程组
- 【java多线程编程核心技术】1.java多线程技能-笔记总结
- Java多线程编程7--拾遗增补--线程的状态(new,runnable,terminated,timed_waiting,waiting,blocked)
- Java多线程编程核心技术笔记
- 《Java多线程编程核心技术》笔记
- 《Java多线程编程核心技术》-笔记
- 《Java 多线程编程核心技术》学习笔记及总结
- 【java多线程编程核心技术】3.线程间通信 -笔记总结
- 【java多线程编程核心技术】4.Lock的使用-笔记总结
- 【java多线程编程核心技术】5.定时器Timer-笔记总结
- java多线程编程核心技术知识点总结
- 《java多线程编程核心技术》核心笔记(一)
- 《java多线程编程核心技术》核心笔记(二)
- Java多线程编程核心技术 第一章笔记
- Java多线程编程核心技术 阅读笔记
- BZOJ 4176: Lucas的数论 莫比乌斯反演 杜教筛
- 计算机的启动过程(详细)
- ETH在线钱包,非常方便也是最早的以太坊在线钱包
- Java 总结 1118/1119
- 【网安随笔】使用python脚本解密图片
- 【java多线程编程核心技术】7.拾遗增补-笔记总结
- 【Scikit-Learn 中文文档】支持向量机
- Caffe 的可视化 (三) caffe model 的可视化
- 1125: 上三角矩阵的判断
- ViewPager轮播适配器
- const char* 类型形参与LPWSTR 类型的实参不兼容
- gift1
- 1126: 布尔矩阵的奇偶性
- idea上maven项目clean后之后遇到的坑