线程状态验证
public class MyThread extends Thread {
public MyThread() {
System.out.println("构造方法中的状态:" + Thread.currentThread().getState());//RUNNABLE
}
@Override
public void run() {
System.out.println("run方法中的状态:" + Thread.currentThread().getState());//RUNNABLE
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
System.out.println("main方法中的状态1:" + thread.getState());//NEW
Thread.sleep(1000);
thread.start();
Thread.sleep(500);
System.out.println("main方法中的状态2:" + thread.getState());//TIMED_WAITING
Thread.sleep(1200);
System.out.println("main方法中的状态3:" + thread.getState());//TERMINATED
} catch (Exception e) {
e.printStackTrace();
}
}
}

运行程序控制台输出结果如下:

构造方法中的状态:RUNNABLE
main方法中的状态1:NEW
run方法中的状态:RUNNABLE
main方法中的状态2:TIMED_WAITING
main方法中的状态3:TERMINATED

public class Service {
synchronized static public void serviceMethod(){
try {
System.out.println(Thread.currentThread().getName() + "进入了serviceMethod方法");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public class MyThread1 extends Thread {
@Override
public void run() {
Service.serviceMethod();
}
} public class MyThread2 extends Thread {
@Override
public void run() {
Service.serviceMethod();
}
} public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread1 t1 = new MyThread1();
t1.start();
MyThread1 t2 = new MyThread1();
t2.start();
Thread.sleep(2000);
System.out.println("main t1 :" + t1.getState());
System.out.println("main t2 :" + t2.getState());
}
}

运行程序,控制台打印结果如下:

Thread-0进入了serviceMethod方法
main t1 :TIMED_WAITING
main t2 :BLOCKED
Thread-1进入了serviceMethod方法

线程对象关联线程组:1级关联

所谓的1级关联就是父对象中有子对象,但是并不创建孙对象。

public class ThreadA extends Thread {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("ThreadName=" + ThreadA.currentThread().getName());
Thread.sleep(3000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} public class Main {
public static void main(String[] args) {
ThreadA a = new ThreadA();
ThreadB b = new ThreadB();
ThreadGroup group = new ThreadGroup("My-Thread-Group");
Thread aThread = new Thread(group, a);
Thread bThread = new Thread(group, b);
aThread.start();
bThread.start();
System.out.println("活动的线程数:" + group.activeCount());
System.out.println("线程组的名称:" + group.getName());
}
}

运行程序,控制台打印结果如下:

活动的线程数:2
ThreadName=Thread-3
ThreadName=Thread-2
线程组的名称:My-Thread-Group
ThreadName=Thread-3
ThreadName=Thread-2
ThreadName=Thread-3
ThreadName=Thread-2
......
线程对象关联线程组:多级关联

所谓的多级关联就是父对象中有子对象,子对象中再创建子对象,也就是出现孙对象的效果。

public class Main {
public static void main(String[] args) {
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
ThreadGroup group = new ThreadGroup(mainGroup, "A");
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println("run method");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread newThread = new Thread(group, runnable);
newThread.setName("Z");
newThread.start();
ThreadGroup[] listGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
Thread.currentThread().getThreadGroup().enumerate(listGroup);
System.out.println("main线程中有" + listGroup.length + "个子线程,名字:" + listGroup[0].getName());
Thread[] listThread = new Thread[listGroup[0].activeCount()];
listGroup[0].enumerate(listThread);
System.out.println(listThread[0].getName());
}
}

运行程序控制台打印结果如下:

run method
main线程中有1个子线程,名字:A
Z

此种写法在开发中不常见,太复杂不利于管理。


如果实例化线程组时不指定所属的线程组,则实例化的线程组归到当前线程对象所属的线程组中

public class Main {
public static void main(String[] args) {
System.out.println("当前线程名:" + Thread.currentThread().getName());
System.out.println("所属线程组:" + Thread.currentThread().getThreadGroup().getName());
System.out.println("线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup group = new ThreadGroup("New-group");
System.out.println("线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup[] threadGroups = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
Thread.currentThread().getThreadGroup().enumerate(threadGroups);
for (int i = 0; i < threadGroups.length; i++) {
System.out.println("第" + (i + 1) + "个线程组名字为:" + threadGroups[i].getName());
}
//如果实例化线程组时不指定所属的线程组,则实例化的线程组归到当前线程对象所属的线程组中
}
}

运行以上程序,控制台打印结果如下:

当前线程名:main
所属线程组:main
线程组数量:0
线程组数量:1
第1个线程组名字为:New-group

获取根线程组

//获取根线程组
public class Main {
public static void main(String[] args) {
System.out.println("当前线程名:" + Thread.currentThread().getName());
System.out.println("所属线程组:" + Thread.currentThread().getThreadGroup().getName());
System.out.println("当前线程所属线程组的父线程组名:" + Thread.currentThread().getThreadGroup().getParent().getName());
System.out.println("当前线程所属线程组的父线程组的父线程组名:" + Thread.currentThread().getThreadGroup().getParent().getParent().getName());
}
}

控制台输出结果如下:

当前线程名:main
所属线程组:main
当前线程所属线程组的父线程组名:system
Exception in thread "main" java.lang.NullPointerException
at com.umgsai.thread.thread66.Main2.main(Main2.java:9)

运行结果说明JVM的根线程组是system,再取其父线程组则抛出空指针异常。


线程组里加线程组

public class Main3 {
public static void main(String[] args) {
System.out.println("线程组名:" + Thread.currentThread().getThreadGroup().getName());
System.out.println("线程组中活动线程数:" + Thread.currentThread().getThreadGroup().activeCount());
System.out.println("线程组中线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup group = new ThreadGroup(Thread.currentThread().getThreadGroup(), "newGroup");
System.out.println("线程组中线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
System.out.println("父线程组名称:" + Thread.currentThread().getThreadGroup().getParent().getName());
}
}

控制台输出结果如下:

线程组名:main
线程组中活动线程数:1
线程组中线程组数量:0
线程组中线程组数量:1
父线程组名称:system

组内的线程批量停止

public class MyThread extends Thread {
public MyThread(ThreadGroup group, String name) {
super(group, name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "准备开始死循环了");
while (!this.isInterrupted()) {
}
System.out.println(Thread.currentThread().getName() + "结束死循环了");
}
} public class Main {
public static void main(String[] args) {
try {
ThreadGroup group = new ThreadGroup("My-group");
for (int i = 0; i < 5; i++) {
MyThread thread = new MyThread(group, "Thread-" + i);
thread.start();
}
Thread.sleep(5000);
group.interrupt();
System.out.println("调用了interrupt方法");
} catch (Exception e) {
System.out.println("停了");
e.printStackTrace();
}
}
}

控制台输出如下:

Thread-3准备开始死循环了
Thread-2准备开始死循环了
Thread-1准备开始死循环了
Thread-4准备开始死循环了
调用了interrupt方法
Thread-3结束死循环了
Thread-2结束死循环了
Thread-4结束死循环了
Thread-1结束死循环了
Thread-0结束死循环了

递归与非递归取组内对象

public class Main5 {
public static void main(String[] args) {
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
ThreadGroup groupA = new ThreadGroup(mainGroup, "A");
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println("run Method");
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
};
ThreadGroup groupB = new ThreadGroup(groupA, "B");
ThreadGroup[] groups = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
//传入true取得其子组及子孙组
Thread.currentThread().getThreadGroup().enumerate(groups, true);
for (int i = 0; i < groups.length; i++) {
if (groups[i] != null) {
System.out.println(groups[i].getName());
}
}
System.out.println("------");
ThreadGroup[] groups2 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
Thread.currentThread().getThreadGroup().enumerate(groups2, false);
for (int i = 0; i < groups2.length; i++) {
if (groups2[i] != null) {
System.out.println(groups2[i].getName());
} }
}
}

控制台打印结果如下:

A
B
------
A

使线程具有顺序性

public class MyThread extends Thread {
private Object lock;
private String showChar;
private int showNumberPosition;
private int printCount = 0;
volatile private static int addNumber = 1;
public MyThread(Object lock, String showChar, int showNumberPosition) {
super();
this.lock = lock;
this.showChar = showChar;
this.showNumberPosition = showNumberPosition;
}
@Override
public void run() {
try {
synchronized (lock) {
while (true) {
if (addNumber % 3 == showNumberPosition) {
System.out.println(Thread.currentThread().getName() + "-" + addNumber + "-" + showChar);
lock.notifyAll();
addNumber++;
printCount++;
if (printCount == 3) {
break;
}
}else {
lock.wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
Object lock = new Object();
MyThread a = new MyThread(lock, "A", 1);
MyThread b = new MyThread(lock, "B", 2);
MyThread c = new MyThread(lock, "C", 0);
a.start();
b.start();
c.start();
}
}

控制台打印结果如下:

Thread-0-1-A
Thread-1-2-B
Thread-2-3-C
Thread-0-4-A
Thread-1-5-B
Thread-2-6-C
Thread-0-7-A
Thread-1-8-B
Thread-2-9-C

类SimpleDateFormat主要负责日期的转换与格式化,但在多线程的环境中,使用此类容易造成数据转换及处理的不准确,因为SimpleDateFormat类并不是线程安全的。

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 = sdf.parse(dateString);
String newDateString = sdf.format(dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName()
+"报错了,日期字符串:" +dateString
+",转换成的日期为:"+newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[]{"2016-07-01", "2016-07-02", "2016-07-03", "2016-07-04", "2016-07-05", "2016-07-06", "2016-07-07", "2016-07-08", "2016-07-09", "2016-07-10"};
MyThread[] threadArray = new MyThread[10];
for (int i=0; i<threadArray.length; i++) {
threadArray[i] = new MyThread(sdf, dateStringArray[i]);
}
for (int i=0; i<threadArray.length; i++) {
threadArray[i].start();
}
}
}

运行程序,控制台打印结果如下:

Exception in thread "Thread-3" Exception in thread "Thread-5" ThreadName=Thread-8报错了,日期字符串:2016-07-09,转换成的日期为:2016-07-08
Exception in thread "Thread-1" Exception in thread "Thread-4" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1020)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
ThreadName=Thread-6报错了,日期字符串:2016-07-07,转换成的日期为:2070-12-07
ThreadName=Thread-2报错了,日期字符串:2016-07-03,转换成的日期为:0010-12-07
ThreadName=Thread-7报错了,日期字符串:2016-07-08,转换成的日期为:0000-12-07
at com.umgsai.thread.thread67.MyThread1.run(MyThread1.java:20)
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "66E16E16E1"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.umgsai.thread.thread67.MyThread1.run(MyThread1.java:20)
java.lang.NumberFormatException: For input string: "66E"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:441)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2088)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.umgsai.thread.thread67.MyThread1.run(MyThread1.java:20)
java.lang.NumberFormatException: For input string: "...7076"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:430)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.umgsai.thread.thread67.MyThread1.run(MyThread1.java:20)
java.lang.NumberFormatException: For input string: "66E16E1"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.umgsai.thread.thread67.MyThread1.run(MyThread1.java:20)

解决方法1:

public class DateUtil {
public static String format(String formatPattern, Date date){
return new SimpleDateFormat(formatPattern).format(date).toString();
} public static Date parse(String formatPattern, String dateString) throws ParseException{
return new SimpleDateFormat(formatPattern).parse(dateString);
}
} public class MyThread extends Thread {
private String dateString; public MyThread(String dateString) {
super();
this.dateString = dateString;
} @Override
public void run() {
try {
Date dateRef = DateUtil.parse("yyyy-MM-dd", dateString);
String newDateString = DateUtil.format("yyyy-MM-dd" ,dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName()
+"报错了,日期字符串:" +dateString
+",转换成的日期为:"+newDateString);
}else{
System.out.println("转换正确");
}
} catch (ParseException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
String[] dateStringArray = new String[]{"2016-07-01", "2016-07-02", "2016-07-03", "2016-07-04", "2016-07-05", "2016-07-06", "2016-07-07", "2016-07-08", "2016-07-09", "2016-07-10"};
MyThread[] threadArray = new MyThread2[10];
for (int i=0; i<threadArray.length; i++) {
threadArray[i] = new MyThread(dateStringArray[i]);
}
for (int i=0; i<threadArray.length; i++) {
threadArray[i].start();
}
}
}

运行程序,控制台打印结果如下:

转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确

此时每个线程分别使用自己独立的SimpleDateFormat对象,不会出现线程安全问题。

解决方法2:

public class DateTools {
private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<>();
public static SimpleDateFormat getSimpleDateFormat(String dateParttern) {
SimpleDateFormat sdf = null;
sdf = t1.get();
if (sdf == null) {
sdf = new SimpleDateFormat(dateParttern);
t1.set(sdf);
}
return sdf;
}
} public class MyThread extends Thread {
private String dateString; public MyThread(String dateString) {
super();
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);
}else{
System.out.println("转换正确");
}
} catch (ParseException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
String[] dateStringArray = new String[]{"2016-07-01", "2016-07-02", "2016-07-03", "2016-07-04", "2016-07-05", "2016-07-06", "2016-07-07", "2016-07-08", "2016-07-09", "2016-07-10"};
MyThread[] threadArray = new MyThread[10];
for (int i=0; i<threadArray.length; i++) {
threadArray[i] = new MyThread(dateStringArray[i]);
}
for (int i=0; i<threadArray.length; i++) {
threadArray[i].start();
}
}
}

运行程序,控制台打印结果如下:

转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确
转换正确

线程中出现异常的处理

在Java多线程中,可以对多线程中的异常进行“捕捉”,使用的是UncaughtExceptionHandler类。

public class MyThread extends Thread {
@Override
public void run() {
String username = null;
System.out.println(username.hashCode());
} public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.setName("线程1");
t1.setUncaughtExceptionHandler(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("线程2");
t2.start();
}
}

运行程序,控制台打印结果如下:

Exception in thread "线程2" 线程1出现了异常
java.lang.NullPointerException
at com.umgsai.thread.thread69.MyThread.run(MyThread.java:7)
java.lang.NullPointerException
at com.umgsai.thread.thread69.MyThread.run(MyThread.java:7)

setUncaughtExceptionHandler()是给指定的线程对象设置异常处理器。在Thread类中可以使用setDefaultUncaughtExceptionHandler()方法对所有线程对象设置异常处理器。

public class MyThread extends Thread {
@Override
public void run() {
String username = null;
System.out.println(username.hashCode());
} public static void main(String[] args) {
MyThread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + "出现了异常");
e.printStackTrace();
}
});
MyThread t1 = new MyThread();
t1.setName("线程1");
t1.start();
MyThread t2 = new MyThread();
t2.setName("线程2");
t2.start();
}
}

运行程序,控制台打印结果如下:

线程1出现了异常
线程2出现了异常
java.lang.NullPointerException
at com.umgsai.thread.thread69.MyThread.run(MyThread.java:7)
java.lang.NullPointerException
at com.umgsai.thread.thread69.MyThread.run(MyThread.java:7)

线程组内处理异常

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 (true) {
System.out.println(Thread.currentThread().getName() + "死循环中");
}
} public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("线程组1");
MyThread[] myThreads = new MyThread[10];
for (int i = 0; i < myThreads.length; i++) {
myThreads[i] = new MyThread(group, "线程" + i, "" + i);
myThreads[i].start();
}
MyThread myThread = new MyThread(group, "报错线程", "a");
myThread.start();
}
}

运行程序后,出错的线程抛出异常后停止,其他线程仍然正常执行。

如果要使一个线程抛异常后同组内其他线程都停止执行可以做如下修改:

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 com.umgsai.thread.thread71; 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()) {
System.out.println(Thread.currentThread().getName() + "死循环中");
}
} public static void main(String[] args) {
MyThreadGroup group = new MyThreadGroup("线程组1");
MyThread[] myThreads = new MyThread[10];
for (int i = 0; i < myThreads.length; i++) {
myThreads[i] = new MyThread(group, "线程" + i, "" + i);
myThreads[i].start();
}
MyThread myThread = new MyThread(group, "报错线程", "a");
myThread.start();
}
}

运行程序,报错线程抛出异常后,其他线程都停止了执行。


线程异常处理的传递

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));
}
} public class ObjectUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("对象的异常处理");
e.printStackTrace();
} } public class StateUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("静态的异常处理");
e.printStackTrace();
}
} public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
MyThread.setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler());
myThread.setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler());
myThread.start();
}
}

运行程序,控制台打印结果如下:

对象的异常处理
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)

对以上程序做如下修改:

public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
MyThread.setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler());
//myThread.setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler());
myThread.start();
}
}

重新运行程序,控制台打印结果如下:

静态的异常处理
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)

继续修改以上代码:

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();
}
} public class Main {
public static void main(String[] args) {
MyThreadGroup group = new MyThreadGroup("我的线程组");
MyThread myThread = new MyThread(group, "我的线程");
MyThread.setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler());
myThread.setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler());
myThread.start();
}
}

运行程序,控制台打印结果如下:

对象的异常处理
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)

继续修改以上代码:

public class Main {
public static void main(String[] args) {
MyThreadGroup group = new MyThreadGroup("我的线程组");
MyThread myThread = new MyThread(group, "我的线程");
MyThread.setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler());
//myThread.setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler());
myThread.start();
}
}

运行程序,控制台打印结果如下:

静态的异常处理
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)
线程组的异常处理
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)

继续修改以上代码:

public class Main {
public static void main(String[] args) {
MyThreadGroup group = new MyThreadGroup("我的线程组");
MyThread myThread = new MyThread(group, "我的线程");
//MyThread.setDefaultUncaughtExceptionHandler(new StateUncaughtExceptionHandler());
//myThread.setUncaughtExceptionHandler(new ObjectUncaughtExceptionHandler());
myThread.start();
}
}

运行程序,控制台打印结果如下:

Exception in thread "我的线程" java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)
java.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 com.umgsai.thread.thread72.MyThread.run(MyThread.java:13)

Java多线程编程核心技术---拾遗增补的更多相关文章

  1. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  2. 《Java多线程编程核心技术》知识梳理

    <Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...

  3. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  4. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  5. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  6. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

  7. 《Java 多线程编程核心技术》- 笔记

    作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...

  8. Thread.currentThread()和this的区别——《Java多线程编程核心技术》

    前言:在阅读<Java多线程编程核心技术>过程中,对书中程序代码Thread.currentThread()与this的区别有点混淆,这里记录下来,加深印象与理解. 具体代码如下: pub ...

  9. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

随机推荐

  1. 负载均衡下的资源文件配置/多站点下的资源文件夹共享(Windows IIS)

    前言: 负载均衡用的是NLB,微软的方案不太靠谱,举个例子吧,AB两台服务器负载出C,如果用户访问访问C之后分配的是A,那么如果A挂了,是不会自动切换到B的.据说后来还有一种NLB的方案可以实现,也不 ...

  2. 未在本地计算机上注册"microsoft.ACE.oledb.12.0"提供程序解决办法

    错误信息:未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序. 解决办法: 去http://download.microsoft.com/download/7/0/3/7 ...

  3. COGS103&tyvj1899 [NOIP2002]矩形覆盖

    题目里给的范围是k<=4,但是官方数据并没有k==4的情况,导致一些奇奇怪怪的DP写法也能过.听说标程在k==4的时候有反例,掀桌-.. 难怪COGS上k==4的数据答案是错的. 还是好好写个搜 ...

  4. ansible模块debug

    示例: # Example that prints the loopback address and gateway for each host - debug: msg="System { ...

  5. iOS应用第三方推送的添加

    现在的一些第三方的推送平台挺好用,主要是因为他们有类似微信公众平台一样的管理后台,简单易用,封装了很多开发者需要的推送功能. 下面以个推为例: 1.在个推的应用配置iOS部分设置自己的BounleID ...

  6. python print输出unicode字符

    命令行提示符下,python print输出unicode字符时出现以下 UnicodeEncodeError: 'gbk' codec can't encode character '\u30fb ...

  7. 屠蛟之路_乘风破浪_FifthDay

    乘风破浪 一艘大船 (我们写的几千行代码) 一片汪洋 (软工耗费的时间) 一群骚年 (一不小心就火了) 为救一位公主 (吃自助餐) 选择去跋山涉水,乘风破浪(解决bug,解决冲突) 毫不畏惧 (韧性) ...

  8. Beta版本——第七次冲刺博客

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  9. 个人作业—Week2:微软必应词典案例分析

    调研.评测 bug报告: 标题:Window 10版必应词典客户端口语练习功能无法使用 环境:Window 10, 微软必应词典(UWP) 版本2.6.1.0,屏幕无重力感应模块 重现步骤: 1)   ...

  10. Linux以外的开源操作系统大汇总

    开源操作系统即公开源代码的操作系统软件,它遵循开源协议使用.编译和发布.自由和开放源代码软件中最著名的是Linux,它是一种类Unix的操作系统.Linux可安装在各种计算机硬件设备中,比如手机.平板 ...