java 并发编程
线程组管理
线程组:
- 线程的集合
- 大线程可包含小线程、
- 可管理多个线程,但效率较低
- 重复的创建线程和关闭线程
- 可通过enumerate显示所有线程
例:
使用线程组创建10个线程,每创建一个线程,休息1秒。
输出活跃的线程,所有线程列表。当活跃的线程数少于8个时,终止所有的线程。
其中,Reacher类为实现Runnable接口的类,Result类为一个存储数据的类。
package ThreadGroup;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ThreadGroup threadgroup = new ThreadGroup("Peter");
Result result = new Result(null);
Reacher reacher = new Reacher(result);
int i = 0;
for(; i < 10; i++) {
Thread thread = new Thread(threadgroup, reacher);
thread.start();
try {
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("=========线程组创建完成==========");
System.out.println("活跃的线程数量为:" + threadgroup.activeCount());
System.out.println("所有线程为:");
threadgroup.list();
System.out.println("===============================");
Thread[] threads = new Thread[threadgroup.activeCount()];
threadgroup.enumerate(threads);//将线程组中所有活跃的线程copy到数组中
for(i = 0; i < threadgroup.activeCount(); i++)
System.out.println(threads[i].getName() +": " + threads[i].getState());
System.out.println("===============================");
waitfinish(threadgroup);
threadgroup.interrupt();
}
public static void waitfinish(ThreadGroup threadgroup) {
while(threadgroup.activeCount() > 8) {
try {
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
package ThreadGroup;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Reacher implements Runnable{
private Result result;
public Reacher(Result result) {
this.result = result;
}
public void run() {
String name = Thread.currentThread().getName();
System.out.println("Thread" + name + "启动");
try {
doTask();
result.setName(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doTask() throws InterruptedException {
Random random = new Random((new Date()).getTime());
int value = (int)(random.nextDouble()*50);
System.out.printf("Thread %s : %d\n", Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
}
package ThreadGroup;
public class Result {
public String name;
public Result(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Executor 框架
该框架可分离认任务的创建和任务的执行,线程可重复利用。(new开销大)
共享线程池:
- 预设好多个线程,多次执行多个小任务;
- 无需关心其他线程的执行过程;
- 任务创建与执行解耦合。
主要类:
ExecutorService,ThreadPoolExecutor,Future。
创建线程池:Executors.newCachedThreadPool/newFixedThreadPool。
线程池服务:ExecutorService。
具体的逻辑对象:Callable。
输出结果:Future。
例子:
main方法中:创建线程池,10个线程,创建线程安全的列表存储结果。
SumTask是一个实现Callable的接口。
(Callable与Runnabl基本一致,只是在实现的call方法中有返回值。)
SumTask类计算某一段的数据和,并返回。
依次创建并将该线程加入到线程池中。
当所有线程都完成后,计算总和。
package executor;
import java.util.concurrent.Future;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class TestTask {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(10);
List<Future<Integer>> resultList = Collections.synchronizedList(new ArrayList<Future<Integer>>());
int i;
for(i = 0; i < 10; i++) {
SumTask caculator = new SumTask(i*100+1, (i+1)*100 + 1);
Future<Integer> result = executor.submit(caculator);
resultList.add(result);
}
do {
System.out.println("已完成的任务数:" + executor.getCompletedTaskCount());
for(i = 0; i < resultList.size(); i++) {
Future<Integer> result = resultList.get(i);
System.out.printf("Task %d: %s\n", i, result.isDone());
try {
Thread.sleep(50);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}while(executor.getCompletedTaskCount() < resultList.size());
int total = 0;
for(i = 0; i < resultList.size(); i++) {
Future<Integer> result = resultList.get(i);
total += result.get();
}
System.out.println("1-1000的总和为:" + total);
executor.shutdown();
}
}
package executor;
import java.util.concurrent.Callable;
public class SumTask implements Callable<Integer>{
private int startNum;
private int endNum;
public SumTask(int startNum, int endNum) {
this.startNum = startNum;
this.endNum = endNum;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i = startNum; i < endNum+1; i++) {
sum = sum + i;
}
System.out.println(Thread.currentThread().getName() + "的和为:" + sum);
return sum;
}
}
Fork-Join框架
该框架适用于整体任务量不确定的场合。实现分治编程(分解,治理合并)。
关键类:
ForkJoinPool:任务池。
定义具体的任务:
RecursiveAction,RecursiveTask。
框架实现步骤:
- 创建线程池;
- 创建任务;
- 提交任务,获取结果;
- 监视过程;
- 输出结果。
例子:
创建线程池,个数为8。
创建任务,并且提交任务,只需提交一次。
在SumTask线程中, 继承RecursiveTask,实现compute方法。
依照分解的思路逐步展开,并不断提交任务。
package ForkJoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class MainTask {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ForkJoinPool pool = new ForkJoinPool(8);
SumTask task = new SumTask(1, 1000000);
ForkJoinTask<Long> result = pool.submit(task);
do {
System.out.println("正在活跃的线程数:" + pool.getActiveThreadCount());
System.out.println("正在并行的线程数:" + pool.getParallelism());
try {
Thread.sleep(50);
}catch(InterruptedException e) {
e.printStackTrace();
}
}while(!result.isDone());
System.out.println("1-100000d的和为:" + result.get().toString());
}
}
//任务线程
package ForkJoin;
import java.util.concurrent.RecursiveTask;
public class SumTask extends RecursiveTask<Long>{
private static final long serialVersionUID = 1L;
private int start;
private int end;
public SumTask(int s, int e) {
start = s;
end = e;
}
@Override
protected Long compute() {
Long sum = (long) 0;
int threadhold = 4;
if((end - start) < threadhold) {
for(int i = start; i < end + 1; i++)
sum += i;
}
else {
int mid = (end - start)/2 + start;
SumTask task1 = new SumTask(start, mid);
SumTask task2 = new SumTask(mid + 1, end);
invokeAll(task1, task2);//提交自任务
Long sum1 = task1.join();//等待子任务完成。
Long sum2 = task2.join();
sum = sum1 + sum2;
}
return sum;
}
}