标签:gate catch card count() ring 计算 监控 cal 思想
JDK提供了一套Executer框架,可以帮助开发人员,有效的进行线程控制,其中newFixedThreadPool(),newSingleThreadExecutor(),newCachedThreadPool均使用了 ThreadPoolExecutor,下面部分就是了解ThreadPoolExecutor
public class newMyThreadPool {
public static void main (String[] args) {
AtomicInteger ai = new AtomicInteger(0);
//创建线程池
//饱和策略默认使用的 abortPolicy(流产策略) : 表示无法处理提交的新任务,抛出异常
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 10, TimeUnit.DAYS, new ArrayBlockingQueue<>(10),new ThreadPoolExecutor.DiscardOldestPolicy());
//提交100个线程任务
for (int i=0;i<100;i++){
//提交带返回值的线程任务
Future<String> future = threadPoolExecutor.submit(new Callable<String>() {
@Override
public String call(){
ai.getAndIncrement();
return Thread.currentThread().getName();
}
});
try {
System.out.println("线程名字:"+future.get()+"执行结果"+future.isDone());
System.out.println("线程数为"+ai);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
/* // 提交不带返回值的线程任务
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});*/
}
threadPoolExecutor.shutdown();
}
}
参数名 | 解释 |
---|---|
corePoolSize | 线程池的基本大小,运行时,当任务提交过来了,如果线程池中的线程数小于corePoolSize,即便当前的线程数够用了,也会继续创建新线程,当作辅助线程 |
maximumPoolSize | 线程中最大的线程数量 |
keepAliveTime | 当线程池中线程的数量达到corePoolSize的时候,此参数为到终止前,超出了corePoolSize的多余线程等待新任务的最长时间,时间到了还没有任务,就被销毁 |
unit | keepAliveTime的时间单位 |
workQueue | 任务队列,保存被提交的尚未执行的任务,(仅仅保存由execute方法提交的 Runable 任务) |
threadFactory | 执行程序创建新线程时使用的工厂。一般使用默认的即可 |
handler | 拒绝策略,当任务太多,来不及处理时,如何拒绝的策略 |
workQueue
handler
RejectedExecutionHandler饱和策略,当线程池和队列都满了,这个时候,又来了新的任务,那么久必须采用一种策略处理新的任务,这个策略默认使用的是abortPolicy,(流产策略,表示无法处理新任务而抛出异常)
// 提交不带返回值的线程任务
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});*/
//提交带返回值的线程任务
Future<String> future = threadPoolExecutor.submit(new Callable<String>() {
@Override
public String call(){
ai.getAndIncrement();
return Thread.currentThread().getName();
}
});
try {
System.out.println("线程名字:"+future.get()+"执行结果"+future.isDone());
System.out.println("线程数为"+ai);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
区别
相同点
都是遍历线程池中的工作线程,挨个调用它们的interrupt()方法
根据任务的特性,合理配置线程池
方法名 | 描述 |
---|---|
beforeExecute(Thread t, Runnable r) | 在Runable执行任务之前调用 |
afterExecute(Runnable r, Throwable t) | Runnable任务执行完后调用 |
getActiveCount() | 主动执行任务的近似线程数 |
等等..
如果ThreadPoolExecutor是一个线程池,那么Executors就是一个线程池工厂
java.util.concurrent
类 Executors
java.lang.Object
继承者 java.util.concurrent.Executors
Executor是一个很灵活的基于接口的任务执行工具,使用它可以极为简单的创建出一个很棒的任务工作队列,却只需要一行代码
ExecutorService executor = Executors.newCachedThreadPool();
提交一个Runable方法
executor.execute(Runable);
优雅的终止
executor.shutdown();
在<
>中提及,executor和task优先于线程,尽量不要编写自己的工作队列,而且尽量不要直接使用线程,现在的关键,不再是Thread了,它既是工作单元也就是任务(task),又是执行机制,而现在工作单元和执行机制是分开的,工作单元就是Runable和它的近亲Callable,而执行机制是 executor service,当我从任务的角度上问题,并让executor service替我们执行任务,那么我们在策略的选择上就有很大的灵活性,从本质上将,Executor Famework所做的事,就是替我们优雅的执行任务
public class Executorsextends Object此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。此类支持以下各种方法:
创建并返回设置有常用配置字符串的 ExecutorService 的方法。
创建并返回设置有常用配置字符串的 ScheduledExecutorService 的方法。
创建并返回“包装的”ExecutorService 方法,它通过使特定于实现的方法不可访问来禁用重新配置。
创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
创建并返回非闭包形式的 Callable 的方法,这样可将其用于需要 Callable 的执行方法中。
使用Executors的工厂方法,可以简单粗暴的获取我们想要的线程池
public static ExecutorService newFixedThreadPool(10);
查看他的实现,可以看到,其实他就是使用ThreadPoolService实现的
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool();
为什么单个线程还整一个线程池? 因为 new 出来的线程在执行任务时如果挂掉了,那么任务就不会被继续执行下去,而使用线程池,虽然只有一个线程,但是线程挂掉后,依然会创建出新的线程执行任务...(用于更新本地或远程日志,或者时间分发线程)
public static ExecutorService newSingleThreadExecutor();
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
简单使用
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
/*
while (true) {
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("-->" + Thread.currentThread().getName());
}
}, 5, TimeUnit.SECONDS);
}
*/
ScheduledFuture<String> schedule = scheduledExecutorService.schedule(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName());
return Thread.currentThread().getName();
}
}, 3, TimeUnit.SECONDS);
try {
System.out.println(schedule.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
JDK8新添加:
public static ExecutorService newWorkStrealingPool
使用:
public static void main(String[] args) {
ExecutorService pool = Executors.newWorkStealingPool(Runtime.getRuntime().availableProcessors());
for (int i=0;i<50;i++){
pool.submit(new Runnable() {
@Override
public void run() {
Date date = new Date();
System.out.println("线程"+Thread.currentThread().getName()+"完成任务,时间为:"+date.getTime());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
while (true){}//主线程自旋,不然看不见效果
}
参考书籍<
标签:gate catch card count() ring 计算 监控 cal 思想
原文地址:https://www.cnblogs.com/ZhuChangwu/p/11150320.html