目录
一、Thread/Runnable/Thread组管理
- 线程的集合,
- 树形结构,大线程组可以包括小线程组,
- 可以通过enumerate方法遍历组内进程执行操作,
- 能有效的管理多个进程,但是还是存在管理效率低,
- 任务分配和执行过程高度耦合,
- 重复创建线程,关闭线程操作,无法重用线程。
1.创建线程组:ThreadGroup threadGroup = new ThreadGroup("Searcher");
2.将线程绑定到线程组中方法(此处需注意线程用Runnable方法实现):Thread thread=new Thread(threadGroup, searchTask);
3.遍历线程组方法:
Thread[] threads=new Thread[threadGroup.activeCount()];//初始化线程数组
threadGroup.enumerate(threads);//将线程组中的各个线程放入线程数组中去
for (int i=0; i<threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s\n",threads[i].getName(),threads[i].getState());//输出线程的名字和状态
}
示例1:
package threadgroup;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
// 创建线程组
ThreadGroup threadGroup = new ThreadGroup("Searcher");
Result result=new Result();
// 创建一个任务,以serchTask为模板10个线程完成
Searcher searchTask=new Searcher(result);
for (int i=0; i<10; i++) {
Thread thread=new Thread(threadGroup, searchTask);
thread.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("========华丽丽0=======");
// 查看线程组消息
System.out.printf("active 线程数量: %d\n",threadGroup.activeCount());
System.out.printf("线程组信息明细\n");
threadGroup.list();
System.out.println("========华丽丽1=======");
// 遍历线程组
Thread[] threads=new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i=0; i<threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s\n",threads[i].getName(),threads[i].getState());
}
System.out.println("========华丽丽2=======");
// Wait for the finalization of the Threadds
waitFinish(threadGroup);
// Interrupt all the Thread objects assigned to the ThreadGroup
threadGroup.interrupt();
}
public static void waitFinish(ThreadGroup threadGroup) {
while (threadGroup.activeCount()>9) {//当十个进程都在运行
try {
TimeUnit.SECONDS.sleep(1);//主线程休息一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package threadgroup;
/**
* 搜索结果类
*
*/
public class Result {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package threadgroup;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Searcher implements Runnable {
private Result result;
public Searcher(Result result) {
this.result=result;
}
@Override
public void run() {
String name=Thread.currentThread().getName();
System.out.printf("Thread %s: 启动\n",name);
try {
doTask();
result.setName(name);
} catch (InterruptedException e) {
System.out.printf("Thread %s: 被中断\n",name);
return;
}
System.out.printf("Thread %s: 完成\n",name);
}
private void doTask() throws InterruptedException {
Random random=new Random((new Date()).getTime());
int value=(int)(random.nextDouble()*100);
System.out.printf("Thread %s: %d\n",Thread.currentThread().getName(),value);
TimeUnit.SECONDS.sleep(value);
}
}
二、Executor:
- 线程可以重复利用(不用每次都new),分离任务和执行者的创建。
- 程序员无需关心线程池执行任务的过程,预先设好多个Thread,可弹性增加。
- callable接口实现线程可以返回值
实现方法,首先线程类中需要实现Callable接口,同时实现call方法返回相关值。
1.创建线程池ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);(线程池容量为4,若不指定则线程池的容量会随线程的增多而增大)
2.建立链表List<Future<Integer>> resultList=new ArrayList<>();来保存结果返回
3.提交线程到线程池中运行Future<Integer> result=executor.submit(calculator);
4.根据链表存储获取每一个线程的结果,再isDone判断是否线程计算结束
5.再根据get函数线程结果中提取计算结果
具体代码示例2:
package executor.example2;
import java.util.Random;
import java.util.concurrent.Callable;
public class SumTask implements Callable<Integer> {
//定义每个线程计算的区间
private int startNumber;
private int endNumber;
public SumTask(int startNumber, int endNumber){
this.startNumber=startNumber;
this.endNumber=endNumber;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i=startNumber; i<=endNumber; i++)
{
sum = sum + i;
}
Thread.sleep(new Random().nextInt(1000));
System.out.printf("%s: %d\n",Thread.currentThread().getName(),sum);
return sum;
}
}
package executor.example2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class SumTest {
public static void main(String[] args) {
// 执行线程池
ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);
List<Future<Integer>> resultList=new ArrayList<>();
//统计1-1000总和,分成10个任务计算,提交任务
for (int i=0; i<10; i++){
SumTask calculator=new SumTask(i*100+1, (i+1)*100);
Future<Integer> result=executor.submit(calculator);
resultList.add(result);
}
// 每隔50毫秒,轮询等待10个任务结束
do {
System.out.printf("Main: 已经完成多少个任务: %d\n",executor.getCompletedTaskCount());
for (int i=0; i<resultList.size(); i++) {
Future<Integer> result=resultList.get(i);
System.out.printf("Main: Task %d: %s\n",i,result.isDone());//当isDone为true则线程结束
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (executor.getCompletedTaskCount()<resultList.size());
// 所有任务都已经结束了,综合计算结果
int total = 0;
for (int i=