天天看點

第一章 Thread Management(線程管理) 下1、使用local thread變量2、線程組3、處理線程組的異常 4、通過工廠建立線程

涉及内容

  • 建立和運作一個線程
  • 擷取和設定線程資訊
  • 打斷一個線程
  • 控制打斷的線程
  • 休眠和喚醒線程
  • 等待線程的終止
  • 建立和運作守護線程
  • 處理線程中不受控制的異常
  • 使用local thread變量
  • 将線程加入組
  • 處理線程組的不受控制的異常
  • 通過工廠建立線程

1、使用local thread變量

線程之間共享變量或者不共享變量

例子:local thread 變量機制

外部變量

package com.jack;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class UnsafeTask implements Runnable {

	private Date startDate;

	@Override
	public void run() {

		startDate = new Date();
		System.out.printf("開始線程: %s : %s\n", Thread.currentThread().getId(),startDate);
		try {
			TimeUnit.SECONDS.sleep((int) Math.rint(Math.random()*10));
		}catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.printf("線程完成: %s : %s\n", Thread.currentThread().getId(), startDate);
	}

	public static void main(String[] args) {
		UnsafeTask task = new UnsafeTask();
		for(int i=0; i< 10; i++){
			Thread thread= new Thread(task);
			thread.start();
			try{
				TimeUnit.SECONDS.sleep(2);
				
			} catch (InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}
           

日志:

第一章 Thread Management(線程管理) 下1、使用local thread變量2、線程組3、處理線程組的異常 4、通過工廠建立線程

線程内部變量

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SafeTask implements Runnable{

	private static ThreadLocal<Date> startDate = 
			new ThreadLocal<Date>(){
				@Override
				protected Date initialValue() {
					return new Date();
				}
	};
	
	@Override
	public void run() {

		System.out.printf("開始線程: %s : %s\n", Thread.currentThread().getId(),startDate.get());
		try {
			TimeUnit.SECONDS.sleep((int) Math.rint(Math.random()*10));
		}catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.printf("線程完成: %s : %s\n", Thread.currentThread().getId(), startDate.get());
	}
	
	
	public static void main(String[] args) {
		SafeTask task = new SafeTask();
		for(int i=0; i< 10; i++){
			Thread thread= new Thread(task);
			thread.start();
			try{
				TimeUnit.SECONDS.sleep(2);
				
			} catch (InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}
           

日志:

第一章 Thread Management(線程管理) 下1、使用local thread變量2、線程組3、處理線程組的異常 4、通過工廠建立線程

總結:

  • 1、ThreadLocal裡面有initialValue()初始化方法、set()方法,get()方法,還有remove()方法(移除變量)
  • 2、ThreadLocal線程内私有

2、線程組

有多個線程為一組,一起控制。

例子:建立10個線程組,一起休眠,一起打斷和測試

import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class SearchTask implements Runnable{

	private Result result;
	
	public SearchTask(Result result) {
		super();
		this.result = result;
	}

	@Override
	public void run() {
		String name = Thread.currentThread().getName();
		System.out.printf("線程 %s: 開始\n", name);
		
		try{
			doTask();
			result.setName(name);
		} catch (InterruptedException e){
			System.out.printf("線程 %s: 打斷了\n", name);
			return ;
		}
		System.out.printf("線程 %s: 結束\n", name);
		
	}

	private void doTask() throws InterruptedException {
		
		Random random = new Random((new Date()).getTime());
		int value = (int) (random.nextDouble()*100);
		System.out.printf("線程 %s: %d\n", Thread.currentThread().getName(), value);
		TimeUnit.SECONDS.sleep(value);
	}
	
	public static void main(String[] args) {
		ThreadGroup threadGroup = new ThreadGroup("Searcher");
		Result result = new Result();
		SearchTask searchTask = new SearchTask(result);
		for(int i=0; i<5; i++){
			Thread thread = new Thread(threadGroup, searchTask);
			thread.start();
			try{
				TimeUnit.SECONDS.sleep(1);
				
			} catch (InterruptedException e){
				e.printStackTrace();
			}
			
		}
		System.out.printf("線程的數量:%d\n", threadGroup.activeCount());
		System.out.printf("關于線程組的資訊\n");
		threadGroup.list();
		//判斷處于活躍的線程
		Thread[] threads =new Thread[threadGroup.activeCount()];
		//将線程threads複制到ThreadGroup當中
		threadGroup.enumerate(threads);
		for (int i=0; i<threadGroup.activeCount(); i++){
			System.out.printf("線程=== %s: %s \n", threads[i].getName(),threads[i].getState());
			
		}
		waitFinish(threadGroup);
		threadGroup.interrupt();
	}

	private static void waitFinish(ThreadGroup threadGroup) {
		while(threadGroup.activeCount() >4) {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e){
				e.printStackTrace();
			}
		}
	}

}
           

日志:

第一章 Thread Management(線程管理) 下1、使用local thread變量2、線程組3、處理線程組的異常 4、通過工廠建立線程

總結:

  • 1.建立一個線程組,将線程加入組當中
  • 2、每個線程進行休眠100秒以下
  • 3、檢視目前的線程的狀态都是Time-Waiting
  • 4、threadGroup.interrupted()将所有線程打斷。

3、處理線程組的異常

public class MyThreadGroup extends ThreadGroup {

	public MyThreadGroup(String name) {
		super(name);
	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.printf("線程 %s 已經抛出異常\n",t.
				getId());
		e.printStackTrace(System.out);
		System.out.printf("終結剩下的線程\n");
		interrupt();
	}


}
           
import java.util.Random;

public class Task implements Runnable{

	@Override
	public void run() {
		int result;
		Random random = new Random(Thread.currentThread().getId());
		while(true){
			result = 1000/ ((int)(random.nextDouble()*1000));
			System.out.printf("%s : %f\n", Thread.currentThread().getId(), result);
			if(Thread.currentThread().isInterrupted()){
				System.out.printf("%d : 打斷了\n" ,Thread.currentThread().getId());
				return ;
			}
		}
		
	}

	public static void main(String[] args) {
		MyThreadGroup threadGroup = new MyThreadGroup("MyThreadGroup");
		Task task = new Task();
		for(int i=0; i<2; i++) {
			Thread t = new Thread(threadGroup, task);
			t.start();
		}
	}
	
}
           

總結:

  • 1、建立一個自定義線程組,重寫非檢查異常
  • 2、System.out.printf("%s : %f\n", Thread.currentThread().getId(), result);  這裡 %f抛出異常,然後被線程組捕獲了。
  • 3、選擇處理異常處理器,本線程異常處理-》本組線程異常處理-》預設處理。

4、通過工廠建立線程

通過ThreadFactory接口建立線程對象。

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ThreadFactory;

public class MyThreadFactory implements ThreadFactory {

	private int counter;
	private String name;
	private List<String> stats;
	
	
	public MyThreadFactory(String name) {
		super();
		this.counter = 0;
		this.name = name;
		this.stats = new ArrayList<String>();
	}

	@Override
	public Thread newThread(Runnable r) {
		Thread t = new Thread(r, name +"-Thread_" + counter);
		counter++;
		stats.add(String.format("建立線程 %d 名稱為:%s,時間: %s\n", t.getId(), t.getName(), new Date()));
		return t;
	}

	public String getStats(){
		StringBuffer buffer = new StringBuffer();
		Iterator<String> it = stats.iterator();
		while (it.hasNext()) {
			buffer.append(it.next());
			buffer.append("\n");
		}
		return buffer.toString();
	}
}
           
import java.util.concurrent.TimeUnit;

public class Task implements Runnable{

	@Override
	public void run() {
		try{
			TimeUnit.SECONDS.sleep(1);
		}catch (InterruptedException e){
			e.printStackTrace();
		}
		
	}

	public static void main(String[] args) {
		MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");
		Task task = new Task();
		Thread thread;
		System.out.printf("開始一個線程\n");
		for (int i=0; i<10; i++){
			thread = factory.newThread(task);
			thread.start();
		}
		System.out.printf("工廠的stats:\n");
		System.out.printf("%s\n", factory.getStats());
	}
	
}
           

總結:

1、可以統一管理線程,比如限制線程的數量

2、分析線程的資料狀态

第一章完結。。。。。

繼續閱讀