public interface Executor { //用来执行某一个任务
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
public interface Callable { //带返回值的任务
/**
* Computes a result, or throws an exception if unable to do so
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
The Callable interface is similar to java.lang.Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A
Runnable , however, does not return a result and cannot throw a checked exception. 而Callable的call方法有返回值而且可以抛出异常。
Executors (操作Executor)常用的工具类, 相当于Collections操作集合的, Arrays操作数组
public class Executors {
线程池: 一个线程池加两个队列: 任务队列,已完成任务队列
六种线程池:
- Executors.newFixedThreadPool(5);
- Executors.newCachedThreadPool(); //CachedThreadPool会一直起到系统不能再起新线程为止,默认情况下线程空闲超过60秒钟,线程就自动销毁
- Executors.newSingleThreadExecutor(); //可以保证任务是串行执行,保证前后的顺序
- Executors.newScheduledThreadPool(4); //执行定时任务. 可重复利用线程中的线程。
大多數綫程池背後的原理都是調用TheadPoolExecutor ,通过它可以自定义线程池。 - Executors.newWorkStealingPool(); //newWorkStealingPool默认根据CPU是几核来启多少个线程,每个线程都维护自己的一个队列,当自己空闲时,可以主动去别的线程队列拿任务执行;由于产生的是精灵线程daemon线程(守护线程,后台线程), 主线程不阻塞的话,看不到输出;精灵线程在后台不断运行,只要虚拟机不退出,这个线程就不会退出
- ForkJoinPool 本质上WorkStealingPool与ForkJoinPool 是一种。WorkStealingPool是在ForkJoinPool基础上做了更高层的抽象而已。
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class T11_WorkStrealingPool {
public static void main(String[] args) throws IOException {
ExecutorService service = Executors.newWorkStealingPool();
//newWorkStealingPool默认根据CPU是几核来启多少个线程
//每个线程都维护自己的一个队列,当自己空闲时,可以主动去别的线程队列拿任务执行
System.out.println(Runtime.getRuntime().availableProcessors()); //打印CPU核数
service.execute(new R(1000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(2000));
service.execute(new R(3000));
//由于产生的是精灵线程daemon线程(守护线程,后台线程), 主线程不阻塞的话,看不到输出
//精灵线程在后台不断运行,只要虚拟机不退出,这个线程就不会退出
System.in.read();
}
static class R implements Runnable{
int time;
public R(int time) {
this.time = time;
}
@Override
public void run() {
try{
TimeUnit.MILLISECONDS.sleep(time);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(time+" "+Thread.currentThread().getName());
}
}
}
package com.qqlindy.yxxy.c_026;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class T12_ForkJoinPool {
static int[] nums = new int[1000000];
static final int MAX_NUM = 50000; //每个线程计算的最大任务
static Random r = new Random();
static {
for (int i = 0; i < nums.length; i++) {
nums[i] = r.nextInt(100);
}
//第一个种:使用Java8的 stream api. 最普通的使用for循环。
System.out.println(Arrays.stream(nums).sum());
}
//RecursiveAction无返回结果
// static class AddTask extends RecursiveAction{
// int start , end;
//
// public AddTask(int start, int end) {
// this.start = start;
// this.end = end;
// }
//
// @Override
// protected void compute() {
// if(end - start <= MAX_NUM){ //不到最大计算数,直接计算
// long sum = 0L;
// for (int i = start; i <end ; i++) {
// sum += nums[i];
// }
// System.out.println("from :"+start+" to:"+end+" = "+sum);
// }else {
// int middle = start+(end-start)/2; //分成两半
//
// AddTask subTask1 = new AddTask(start ,middle); //继续fork 就是递归, 由ForkJoinPool帮你维护
// AddTask subTask2 = new AddTask(middle ,end);
// subTask1.fork();
// subTask2.fork();
// }
// }
// }
//RecursiveTask带返回值
static class AddTask extends RecursiveTask<Long>{
int start , end;
public AddTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if(end - start <= MAX_NUM){ //不到最大计算数,直接计算
long sum = 0L;
for (int i = start; i <end ; i++) {
sum += nums[i];
}
// System.out.println("from :"+start+" to:"+end+" = "+sum);
return sum;
}
int middle = start+(end-start)/2; //分成两半
AddTask subTask1 = new AddTask(start ,middle); //继续fork 就是递归, 由ForkJoinPool帮你维护
AddTask subTask2 = new AddTask(middle ,end);
subTask1.fork();
subTask2.fork();
return subTask1.join()+subTask2.join();
}
}
public static void main(String[] args) throws IOException {
ForkJoinPool forkJoinPool = new ForkJoinPool();
AddTask task = new AddTask(0, nums.length);
forkJoinPool.execute(task);
long result = task.join(); //join本身是阻塞的 下面就不用阻塞了。
System.out.println(result);
// System.in.read(); //因为是精灵线程,这里做了个阻塞,为了打印结果。
}
}
/*
计算1万个数。数值在1百万到2百万之间。
*/
public class T14_ParallelStreamApi {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 10000; i++) {
nums.add(1000000+r.nextInt(1000000));
}
long start = System.currentTimeMillis();
nums.forEach(v->isPrime(v));
long end = System.currentTimeMillis();
System.out.println(end-start);
//parallelStream 默認運用多綫程去計算 运行
start = System.currentTimeMillis();
nums.parallelStream().forEach(T14_ParallelStreamApi::isPrime );
end = System.currentTimeMillis();
System.out.println(end-start);
}
/**
* 判断是否是质数
* @param num
* @return
*/
static boolean isPrime(int num){
for (int i = 2; i <= num / 2; i++) {
if(num % i ==0){
return false;
}
}
return true;
}
}