Callable接口总结
1、接口
源码展示: * @see Executor
- @since 1.5
- @author Doug Lea
- @param the result type of method {@code call}
/
@FunctionalInterface
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;
}
可以看到Callable是一个泛型接口 接口里有一个call()方法 返回我们指定的类型;
2、创建线程创建固定数量的可复用的线程数,来执行任务。当线程数达到最大核心线程数,则加入队列等待有空闲线程时再执行池
1、这里我们创建固定线程池(本次采用)
poolSize即为我们线程池的线程数目(这里我们设为10)
ExecutorService pool = Executors.newFixedThreadPool(poolSize)
返回的pool 参数详解 其中
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
nThreads就是poolSize;第一个参数为核心线程数(corePoolSize),就是说线程池应该维护的最小线程的数量,线程池数量小于该值,则来一个新线程时就会创建一个新线程,无论线程池中有无空闲线程;
第二个参数为最大线程数(maximumPoolSize),线程池中最大创建线程的数量;
第三个参数为空闲线程存活时间(keepAliveTime),默认情况下,只有线程池中的线程数大于核心线程数(corePoolSize)时,keepAliveTime才会起作用,直到线程池中的线程数不大于核心线程数(corePoolSize),即当线程池中的线程数大于核心线程数(corePoolSize)时,如果一个线程空闲的时间达到空闲线程存活时间(keepAliveTime),该线程会终止,直到线程池中的线程数不超过核心线程数(corePoolSize),但是如果调用了allowCoreThreadTimeOut(true)方法,在线程池中的线程数不大于核心线程数时(corePoolSize),空闲线程存活时间(keepAliveTime)参数也会起作用,直到线程池中的线程数为0;
第四个参数和空闲线程存活时间(keepAliveTime)同一个参数 指定它是什么单位;
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
第五个参数BlockingQueue workQueue为阻塞的任务队列,用来存储等待执行的任务,有以下几个选择:
1、 ArrayBlockingQueue
2、 LinkedBlockingQueue
3、 SynchronousQueue
4、 PriorityBlockingQueue
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
创建固定数量的可复用的线程来执行任务,
2、我们还可以创建可缓存线程池
ExecutorService cachePool = Executors.newCachedThreadPool();
返回的pool 其中Integer.MAX_VALUE 为int类整数的最大值2的31次方-1=2147483647
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
就是说线程最大数为Integer的最大值 空闲线程存活时间为60L即一分钟; 如果有大量耗时的任务,则不适合该创建方式,它只适合于生命周期短的任务。
3、还可以创建单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();
返回的singlePool
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
只用一个线程来无间歇执行
4、还可以创建固定线程数、支持定时和周期性任务的线程池(poolSize为核心线程数)
ExecutorService schedulePool = Executors.newScheduledThreadPool(poolSize)
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
示例:
package com.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class TestStartPool {
private static final int poolSize=10;//线程池最大为10个
ExecutorService pool=Executors.newFixedThreadPool(poolSize);//创建建一个固定线程池
public static void main(String[] args) {
TestStartPool testStartPool = new TestStartPool();
testStartPool.createPool();
}
/**
* 把执行的任务放到list里 这里我们设置为传两个参数到线程里
*/
public void createPool() {
List<TestPoolExecutor> invokers = new ArrayList<>();
List<String> list=new ArrayList<String>();
int name=0;
for(int a=0;a<poolSize;a++){
name++;
invokers.add(new TestPoolExecutor(list,name));
}
getinvokerfuture(invokers);
}
/**
* 从list里获取执行结果
* @param invokers
*/
public void getinvokerfuture(List<TestPoolExecutor> invokers){
try {
List<Future<List<String>>> futures = pool.invokeAll(invokers, 10, TimeUnit.MILLISECONDS);
for(int a=1;a<futures.size()+1;a++) {
Future<List<String>> thread = futures.get(a - 1);
if(thread !=null){
try {
//获取执行结果
if(thread.isDone()) {
List<String> result = thread.get();
System.out.println("线程"+result.get(0)+"执行结果为"+result.get(1));
}
}catch (Exception e){
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
public class TestPoolExecutor implements Callable<List> {
private List<String> list;
private int name;
private int testnum;
public TestPoolExecutor(List<String> list, int name) {
this.list = list;
this.name = name;
}
@Override
public List<String> call() throws Exception {
System.out.println("线程"+name+"开始执行++++++");
//这里可以写每个线程要执行什么
List<String> testlist=new ArrayList<String>();
testlist.add(String.valueOf(name));//判断是哪个线程
testnum=name+2;
testlist.add(String.valueOf(testnum));//设置为每个线程的执行结果
return testlist;
}
}
线程1开始执行++++++
线程2开始执行++++++
线程6开始执行++++++
线程10开始执行++++++
线程5开始执行++++++
线程9开始执行++++++
线程3开始执行++++++
线程7开始执行++++++
线程4开始执行++++++
线程8开始执行++++++
线程1执行结果为3
线程2执行结果为4
线程3执行结果为5
线程4执行结果为6
线程5执行结果为7
线程6执行结果为8
线程7执行结果为9
线程8执行结果为10
线程9执行结果为11
线程10执行结果为12