JAVA基础23-多线程(二)【线程局部变量和未捕获异常处理器】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a592381841/article/details/84900656

一、线程局部变量

   在线程中使用共享变量肯定是存在风险。为了规避这个风险,利用同步机制,volatile这些方法都可以。但是也可为每个线程分配一个变量。使用ThreadLocal辅助类为各个线程提供各自的实例。

 ThreadLocal为每个使用该变量的线程分配一个独立的变量副本,每一个线程都可以独立地改变自己的副本,而不影响其他线程。

2 ThreadLocal方法及使用示例

  ThreadLocal<T>类在Spring,Hibernate等框架中起到了很大的作用。为了解释ThreadLocal类的工作原理,必须同时介绍与其工作甚密的其他几个类,包括内部类ThreadLocalMap,和线程类Thread。所有方法如下图:

四个核心方法说明如下:

                   T         get()                   返回此线程局部变量的当前线程副本中的值。

 protected  T         initialValue()       返回此线程局部变量的当前线程的“初始值”。

                   void remove()             移除此线程局部变量当前线程的值。

                   void set(T value)         将此线程局部变量的当前线程副本中的值设置为指定值。

package com.demo9aa.demo8;

import java.util.Scanner;

public class Bank extends Thread {
ThreadLocal<Integer> b=new ThreadLocal<>();
	@Override
public void run() {
		Scanner s=new Scanner(System.in);
		System.out.println(Thread.currentThread().getName());
		int i=s.nextInt();
		b.set(i);
		s.close();
		System.out.println(b.get());
	// TODO Auto-generated method stub
	super.run();
}
}

//--------------------------------------------------------------------
package com.demo9aa.demo8;

public class Bb {
public static void main(String[] args) {
	Bank b=new Bank();
	Bank b1=new Bank();
	b.start();
	b1.start();
}
}

二、未捕获异常处理机制

A:场景再现 

run方法不能抛出任何检查性异常,但是对于非检查性异常,则会导致线程异常死亡

         例子如下:

//------------------------------------运行时异常----

//主函数
package com.demo9aa.demo9.demo1;

public class Main {
public static void main(String[] args) {
	Thread a=new Thread(new ThreadA());
	try {
		a.start();	
	} catch (RuntimeException e) {
		// TODO: handle exception
		System.out.println("12313");
	}
	
	
	
}
}


//TheadA


package com.demo9aa.demo9.demo1;

public class ThreadA implements Runnable {

	@Override
	public void run() {
		
		int[] i={1,2};
		System.out.println(i[3]);
		// TODO Auto-generated method stub

	}

}
//运行结果
未输出catch语句
抛出异常,线程终止

B:如何捕获run方法中的检查性异常呢?

B-1:JVM让提供了线程未捕获异常处理机制,

                           通过Thread的静态方法:setDefaultUncaughtExceptionHandler方法设置所有线程的默认未捕获异常处理器

                           通过Thread的成员方法:setUncaughtExceptionHandler方法设置当前线程的未捕获异常处理器

B-2: 默认未捕获异常处理器、特定的未捕获异常处理器

     根据B-1可知,如何设置未捕获处理器

       其运行优先级如下:

                              若特定的Thread对象,设置了未捕获异常处理器,则处理器为:“特定的未捕获异常处理器”

                              若无设置“特定的未捕获异常处理器”,则有如下情况

                                             设置了 “默认未捕获异常处理器”;则处理器为该未捕获异常处理器,

                                             未设置"默认未捕获异常处理器",则处理器为:该线程所对象的ThreadGroup类的对象。

      如下两个图:

C:如何定义未捕获的异常处理器

 处理器必须实现 java.lang.Thread.UncaughtExceptionHandler接口。并实现 void uncaughtException(Thread t,Throwable a)方法。

//-------------------DefaultUncaughtExceptionHandler------
package com.demo9aa.demo9.demo1;

import java.lang.Thread.UncaughtExceptionHandler;

public class DefaultUncaughtExceptionHandler implements UncaughtExceptionHandler {

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println("默认处理器:"+e.getMessage());
		// TODO Auto-generated method stub

	}

}
//--------------------------UncaughtExceptionHandlerA ------------------------
package com.demo9aa.demo9.demo1;

import java.lang.Thread.UncaughtExceptionHandler;

public class UncaughtExceptionHandlerA implements UncaughtExceptionHandler {

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		// TODO Auto-generated method stub
		System.out.println("特定的处理器:"+e.getMessage());

	}

}

D:完整例子

//-----------------ThreadError -------------
package com.demo9aa.demo9.demo1;

public class ThreadError implements Runnable {

	@Override
	public void run() {
		
		int[] i={1,2};
		System.out.println(i[3]);
		// TODO Auto-generated method stub

	}

}
//--------------------------main-----------------
package com.demo9aa.demo9.demo1;

import java.lang.Thread.UncaughtExceptionHandler;

public class Main {
public static void main(String[] args) {
	Thread a=new Thread(new ThreadError());
	a.setUncaughtExceptionHandler(new UncaughtExceptionHandlerA());
      a.start();
      //设置了特定处理器之后
//      a.setUncaughtExceptionHandler(new UncaughtExceptionHandlerA());
//      System.out.println(a.getUncaughtExceptionHandler().getClass().getSimpleName());
	
	
	
	
}
}

//------------------------------输出-------------------------
特定的处理器:java.lang.ArrayIndexOutOfBoundsException: 3

猜你喜欢

转载自blog.csdn.net/a592381841/article/details/84900656
今日推荐