https://www.cnblogs.com/sachen/p/7401959.html
线程池的种类,区别和使用场景
newCachedThreadPool:适用:执行很多短期异步的小程序或者负载较轻的服务器; 高并发 大数据的时候
可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool:适用:执行长期的任务,性能好很多 多用于数据库执行时
定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newSingleThreadExecutor: 适用:一个任务一个任务执行的场景
单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
NewScheduledThreadPool: 适用:周期性执行任务的场景
定长线程池,支持定时及周期性任务执行。
线程池任务执行流程:
当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize:线程池的核心线程数,线程池中运行的线程数也永远不会超过 corePoolSize 个,默认情况下可以一直存活。可以通过设置allowCoreThreadTimeOut为True,此时 核心线程数就是0,此时keepAliveTime控制所有线程的超时时间。
maximumPoolSize:线程池允许的最大线程数;
keepAliveTime: 指的是空闲线程结束的超时时间;
unit :是一个枚举,表示 keepAliveTime 的单位;
workQueue:表示存放任务的BlockingQueue<Runnable队列
@Repository 具有类似用途和功能的@Component注解的特化,为Dao提供了额外的好处,将Dao导入IOC容器,使未经检验的异常有资格转换为Spring DataAccessException
线程池:
https://www.jianshu.com/p/210eab345423
执行任务execute的核心逻辑
线程池运行的四个阶段:
总结:ThreadPoolExecutor基于生产者-消费者模式,提交任务的操作相当于生产者,执行任务的线程相当于消费者;
Executors提供了四种基于ThreadPoolExecutor构造线程池模型的方法,除此之外,我们还可以直接继承ThreadPoolExecutor,重写beforeExecute和afterExecute方法来定制线程池执行任务;
使用有界队列还是无界队列需要根据具体情况考虑,工作队列的大小和线程的数量;
拒绝策略推荐使用CallerRunsPolicy,该策略不会抛弃任务,也不会抛出异常,而是将任务回退到调用者线程中执行;
多线程,最简单的用法就是多个线程。
多个线程一起跑就叫多线程,,,,emmmm,好尬。
一般用于处理多个任务或多个方法时,这个任务需要处理的时间还比较长,可能会产生多个任务,如果正常的采用for循环的形式进行执行,这样需要等到所有任务都执行完系统才会执行下一步 ,这样会造成许多的时间浪费,这算是同步吧,。这时候就需要采用异步的方法,将这些任务去执行,但是不需要关心后期执行过程,(无返回值要求),这样就不会造成长时间的等待了。这种场景需要用多线程。
还有一种情况,一般的采用runnable接口的多线程,run方法无返回值,但是需要采用多线程,有需要使用这个方法的返回值用于其他计算,这时候需要采用callable接口。可以得到返回值。
1.最简单的多个线程一起跑的多线程。(不知道算不算多线程啦)
设计 4 个线程,其中两个线程每次对 j 增加 1,另外两个线程
对 j 每次减少 1。写出程序。
以下程序使用内部类实现线程,对 j 增减的时候没有考虑顺序问题。
public class ThreadTest {
private int j;
public static void main(String args[]){
ThreadTest tt=new ThreadTest();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(int i=0;i<2;i++){
Thread t=new Thread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+ j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(int i=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(int i=0;i<100;i++){
dec();
}
}
}
这个还算是比较经典的多线程算法题吧,
2,采用ExecuteService形式,使用多线程,runnable
https://blog.csdn.net/wanghao_0206/article/details/76460877
这个挺清楚的。
ExecutorService executorService = null;
List<Map<String,Object>> applys = Dao.selectList(msSupplementMapper+"queryLoanApplyAndResult");
if(CollectionUtils.isEmpty(applys)){
return ;
}
executorService = Executors.newFixedThreadPool(applys.size() > 20 ? 20 : applys.size());
for(final Map<String,Object> apply : applys){
final int status = Integer.parseInt(apply.get("status").toString());
final int mainStatus = Integer.parseInt(apply.get("mainStatus").toString());
executorService.execute(new Runnable() {
@Override
public void run() {
// 放款申请成功 || 已发起放款申请 || 放款成功无正式还款计划 -- 发送放款结果查询
if(
(MsStatus.LOAN_APPLY.getCode() == mainStatus && MsStatus.LOAN_APPLY_SUCCESS.getCode() == status) )){
queryLoanResult(apply.get("projectId").toString());
}else{
loanApply(apply.get("projectId").toString());
}
}
});
}
3,采用ExecutorService形式,利用future。
List<Future<PayableSource>> futureList = new ArrayList<>(sumBeginningList.size());
for(SumBeginning sumBeginning : sumBeginningList){
logger.debug("===== 循环遍历 sumBeginning =====");
ChargeBo<SumBeginningQo> chargeBoToRefer = chargeBo.clone();
chargeBoToRefer.setOperator(UserUtil.getCurrentUser(false));
sumBeginningQo = new SumBeginningQo();
sumBeginningQo.setId(sumBeginning.getId());
chargeBoToRefer.setPayableSourceQueryObj(sumBeginningQo);
logger.debug("===== 进入chargeService 逻辑 =====");
futureList.add(executorService.submit(new ChargeService(chargeBoToRefer, SUM_BEGINNING_SERVICE)));
}
logger.debug("<<<<<SumBeginningService.charge");
return futureList;
public ChargeService(ChargeBo chargeBo, PayableService payableService){
this.chargeBo = chargeBo;
this.payableService = payableService;
}
new ChargeService 是实现的callable接口,在call方法实现了返回值。
@Override
public PayableSource call() throws Exception{
logger.debug(">>>>>ChargeService.call");
RPermitExpirableSemaphore semaphore = null;
String permitId = null;
try{
PayableSource queryObj = chargeBo.getPayableSourceQueryObj();
PayableSource payableSource = null;
if(queryObj instanceof SumBeginningPlusQo){
payableSource = payableService.getPayableSourcePlus(queryObj.getId(), true);
logger.debug("===== 代偿跳过扣款验证 =====");
}else{
payableSource = payableService.getPayableSource(queryObj.getId(), true);
payableService.validatePayable(payableSource);
}
return payableSource;
}catch (Exception e){
logger.error("===== ChargeService.call出现异常:", e);
Dao.rollback();
if(e instanceof ActionException){
throw e;
}else{
throw new ActionException(e.getMessage(), e);
}
}finally {
Dao.close();
if(semaphore != null && permitId != null){
semaphore.release(permitId);
}
}
上边list采用的Future模式,用来承接callable方法的,具体的还不太了解。。。emmmm。
https://www.cnblogs.com/cz123/p/7693064.html
。好好学习,差的还有点多