1. 程式人生 > >JAVA基礎23-多執行緒(二)【執行緒區域性變數和未捕獲異常處理器】

JAVA基礎23-多執行緒(二)【執行緒區域性變數和未捕獲異常處理器】

一、執行緒區域性變數

   線上程中使用共享變數肯定是存在風險。為了規避這個風險,利用同步機制,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