java使用jdk的ThreadPoolExecutor线程池

一、使用Executors创建线程池(阿里不推荐使用此方法)

Executors 是一个Java中的工具类。

常用方法:

1、newSingleThreadExecutor:创建一个单线程的线程池,用于需要保证顺序执行的逻辑,只有一个线程在执行。

2、newFixThreadExecutor:创建一个固定大小的线程池,用于已知并发压力下,对线程数做限制。

3、newCachedThreadPool:创建一个可以无限扩大的线程池,比较适合处理执行时间比较短的任务。

4、newScheduledThreadPool:创建一个可以延时启动,定时启动的线程池,用于需要多个后台线程执行周期任务的场景。

5、newWorkSteaLingPool:创建一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。

关闭连接池方法:

1、shutdown():调用后不再接受新的任务

2、shutdownNow():调用后未开始的任务取消,执行中的任务停止执行,并返回未开始任务列表

总结:

1、Executors方法中使用的其实也是ThreadPoolExecutor创建的线程池。

2、以上方法都不支持自定义拒绝策略

3、newSingThreadExecutor和newFixThreadExecutor,可能由于任务堆积,耗费内存变大甚至OOM

4、newCachedThreadPool和newScheduledThreadPool,可能会创建非常多的线程,导致OOM

二、使用ThreadPoolExecutor创建线程池(推荐)

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler);

参数解释:

  corePoolSize : 线程池核心池的大小。

  maximumPoolSize : 线程池的最大线程数。

  keepAliveTime : 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

  unit : keepAliveTime 的时间单位。

  workQueue : 用来储存等待执行任务的队列。

  threadFactory : 线程工厂。(默认Executors.defaultThreadFactory())

  handler  拒绝策略。

原理:

1、刚创建完成线程池后,此时线程池内线程数量为0。

2、有任务过来时,创建线程执行任务,线程数量一直达到corePoolSize 设置的大小。

3、任务数量继续增加时,就把任务放到等待执行队列workQueue 中,队列数量一直达到最大值(队列满了)。

4、任务数量继续增加,此时就又创建新的线程执行任务,线程数量一直达到maximumPoolSize 设置的大小。

5、任务数量继续增加,此时线程数量最大,队列也已满,则开始执行拒绝策略。

阻塞队列:

1、ArrayBlockingQueue(有界队列):基于数组的先进先出队列,创建时需指定大小。

2、LinkedBlockingQueue(无界队列):基于链表的先进先出队列,如果没有指定大小,则默认Integer.MAX_VALUE。

3、synchronousQueue(直接提交队列):不会保存提交的任务,而是直接新建线程来执行

拒绝策略:

1、ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExcetionException异常。(默认)

2、ThreadPoolExecutor.DiscardPolicy:丢弃任务,但不抛出异常。

3、ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后执行新任务。

4、ThreadPoolExecutor.CallerRunPolicy:由调用线程处理该任务。

三、附上Demo

 1、创建一个java线程池

package com.sumengnan.pool;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPool {

    public ThreadPoolExecutor threadPoolExecutor;
    private static ThreadPool uniqueInstance = new ThreadPool();

    private ThreadPool() {
        threadPoolExecutor = new ThreadPoolExecutor(30,//线程池大小30(初始)
                50, //默认最大线程50
                5, //空闲线程保持时间
                TimeUnit.SECONDS,//单位秒
                new LinkedBlockingDeque<>(200),//,等待队列大小200
                new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策略:丢弃队列最前面的任务,然后再添加任务
    }
    /**
     * 获取实例
     * @return
     */
    public static ThreadPool getInstance() {
        return uniqueInstance;
    }
}

 2、创建具体的任务逻辑

package com.sumengnan.test.web;

import com.sumengnan.SumengnanApplication;

public class AddThread implements Runnable {//,Callable<Object>
    @Override
    public void run() {
        //打印次数
        System.out.println("当前第"+ SumengnanApplication.i.incrementAndGet() +"次执行");
    }
    //如果需要关注返回结果,则需要实现Callable接口,否则仅仅实现Runnable接口就可以
    /*@Override
    public String call() throws Exception {
        return "当前第"+ SumengnanApplication.i.incrementAndGet() +"次执行";
    }*/
}

3、创建主类测试

package com.sumengnan;

import com.sumengnan.pool.ThreadPool;
import com.sumengnan.test.web.AddThread;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class SumengnanApplication {

	//java并发机制中主要有三个特性:原子性、可见性和有序性。synchronized关键字只能保证可见性和有序性。
	//volatile关键字保证了静态变量的可见性,如果值发生了变更,其他线程立马可见,避免出现脏读的现象。
	//AtomicInteger类为了保证原子性,其中有一些incrementAndGet自增类的方法。
	public static volatile AtomicInteger i = new AtomicInteger(0);

 	public static void main(String[] args) {
 		//循环230次
		for (int i = 0; i <230; i++) {
			System.out.println("第"+(i+1)+"个任务加入队列");
			ThreadPool.getInstance().threadPoolExecutor.execute(new AddThread());
    		    //如果需要关注返回结果,则需要使用submit方法,任务需实现Callable接口
                /*Future<String> submit = ThreadPool.getInstance().threadPoolExecutor.submit((Callable<String>) new AddThread());
			try {
				System.out.println(submit.get());
			} catch (Exception e) {
				e.printStackTrace();
			}*/
		}
	}
}

4、执行现象如下:

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值