涉及内容
- 建立和運作一個線程
- 擷取和設定線程資訊
- 打斷一個線程
- 控制打斷的線程
- 休眠和喚醒線程
- 等待線程的終止
- 建立和運作守護線程
- 處理線程中不受控制的異常
- 使用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();
}
}
}
}
日志:

線程内部變量
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();
}
}
}
}
日志:
總結:
- 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();
}
}
}
}
日志:
總結:
- 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、分析線程的資料狀态
第一章完結。。。。。