【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); 注释取消后, 线程组的异常处理与静态的异常处理 能一起输出。

阅读全文
0 0
原创粉丝点击