涉及内容
- 创建和运行一个线程
- 获取和设置线程信息
- 打断一个线程
- 控制打断的线程
- 休眠和唤醒线程
- 等待线程的终止
- 创建和运行守护线程
- 处理线程中不受控制的异常
- 使用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、分析线程的数据状态
第一章完结。。。。。