java中线程池的创建以及调用

自定义的线程池使用时直接通过@autowired   ExecutorService executorService注入使用

使用ThreadPoolExecutor创建线程池:

@Bean

public ExecutorService threadPool() {

    int corePoolSize=5,maximumPoolSize=10,keepAliveTime=1,BlockingDequesize=20;

    return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,

           new LinkedBlockingDeque<Runnable>(BlockingDequesize), new ThreadFactory(){

 

              @Override

              public Thread newThread(Runnable r) {

                  Thread t=new Thread(r);

                  t.setDaemon(true);

                  // TODO Auto-generatedmethod stub

                  return t;

              }

      

    });

   

}

ExecutorService.execute(Runnable)为执行线程的方法

ExecutorService.execute(()->system.out.prient("方法体"));在java8中接口直接用()-》后面加代码逻辑去实现。

上面为创建一个线程池并交由spring容器管理,在使用时可使用

@autowired等注解注入使用。在上面参数中,corePoolSize代表核心线程数maximumPoolSize代表线程池最大线程数,keepAliveTime线程池中超过corePoolSize核心线程数目的空闲线程最大存活时间默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用TimeUnit.SECONDSkeepliveTime存活时间单位。BlockingDequesize为线程池队列大小,阻塞队列,用来存储等待执行的任务ThreadFactory为线程池工厂。

队列的类型:

ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。

LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue: 一个不存储元素的阻塞队列。
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。

RejectedExecutionHandler设置拒绝机制为当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理,这个在上面方法中未用到

 

1.    当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
3.workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 

 

ThreadPoolExecutor类中有几个非常重要的方法:
1execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。
2submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果(Future相关内容将在下一篇讲述)。
3shutdown()shutdownNow()是用来关闭线程池的。
4、还有一大波get的方法, 可以获取与线程池相关属性的方法。

 

下面是Executors提供的线程池配置方案 
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
创建方式: Executors.newCachedThreadPool()

newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。定长线程池的大小最好根据系统资源进行设置,如Runtime.getRuntime().availableProcessors()
创建方式: Executors.newFixedThreadPool()

newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
创建方式: Executors.newScheduledThreadPool ()

newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
创建方式: Executors.newSingleThreadExecutor ()

java doc提倡使用Executors来创建线程池,但是alibaba规范文档里面要求使用ThreadPoolExecutor创建线程池。

/异步
        new Thread(new Runnable() {

            @Override
            public void run() {
                /**
                 * 我调用你的方法,在这里向你注册回调接口
                 */
                sysout.out.printin();              
            }
        }).start(); 

 @Bean(destroyMethod = "shutdown")

public ExecutorService threadPool() {

return new ThreadPoolExecutor(corePoolSize, maxPoolSize, idleTime, TimeUnit.SECONDS,            

new LinkedBlockingDeque<Runnable>(blockingDequeSize),            

new ThreadFactory() { int threadId = 2;                

@Override              

  public Thread newThread(Runnable r) {

Thread t = new Thread(r);                    

t.setName("worker thread " + (threadId++));                    

t.setDaemon(true);                    

 if (threadId > 100000) threadId = 2;                  

  return t;                 } },

new ThreadPoolExecutor.CallerRunsPolicy()); }

创建定时线程池:

@Bean(destroyMethod = "shutdown")

public ScheduledExecutorService scheduledExecutorService() {

return new ScheduledThreadPoolExecutor(this.config.getScheduledExecutorCoreSize(), new ThreadFactory() {

int threadId = 1;

@Override

public Thread newThread(Runnable r) {

Thread t = new Thread(r);

t.setName("scheduled-thread-" + (this.threadId++));

t.setDaemon(true);

if (this.threadId > 100000) {

this.threadId = 1;

}

return t; }

}); }

 

@Bean(destroyMethod = "shutdown")
public ExecutorService ruleThreadPool() {

return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactory() {

private int count ;

@Override

public Thread newThread(Runnable runnable) {

if (count > 1000){

count = 0;

}
Thread result = new Thread(runnable, "RuleBuildPool " + count++);

result.setDaemon(true);
return result;

}
});
}

在使用线程池时,我们都知道线程池有两种提交任务的方式,那么他们有什么区别呢?

1.execute提交的是Runnable类型的任务,而submit提交的是Callable或者Runnable类型的任务

2.execute的提交没有返回值,而submit的提交会返回一个Future类型的对象

3.execute提交的时候,如果有异常,就会直接抛出异常,而submit在遇到异常的时候,通常不会立马抛出异常,而是会将异常暂时存储起来,等待你调用Future.get()方法的时候,才会抛出异常

execute只能提交Runnable类型的任务,无返回值。submit既可以提交Runnable类型的任务,也可以提交Callable类型的任务,会有一个类型为Future的返回值,但当任务类型为Runnable时,返回值为null。

具体使用见:【JAVA】向 Callable / Runnable 内部传递参数,在 SpringBoot 中使用_callable传参_JoKKKKKKKKKKKKK的博客-CSDN博客

public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newSingleThreadExecutor();
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("线程处理开始...");
                int a = 0;
                int b = 3;
                System.out.println("除以0的结果为:" + b/a);
                System.out.println("线程处理结束...");
                return "0";
            }
        };
        Future<String> future = es.submit(callable);

 也可使用spring配置文件的方式创建线程,如下在配置文件中添加:

<!-- 线程池配置 -->
<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <!-- 线程池维护线程的最少数量 -->
    <property name="corePoolSize" value="${thread.corePoolSize}"></property>
    <!-- 允许空闲时间 -->
    <property name="keepAliveSeconds" value="${thread.keepAliveSeconds}"></property>
    <!-- 线程池维护线程的最大数量 -->
    <property name="maxPoolSize" value="${thread.maxPoolSize}"></property>
    <!-- 缓存队列 -->
    <property name="queueCapacity" value="${thread.queueCapacity}"></property>
    <!-- 对拒绝task的处理策略 -->
    <property name="rejectedExecutionHandler">
        <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
    </property>
</bean>

使用时直接利用注解注入即可:

@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor;

或者用如下方法创建

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("add-comments-%d").build();
LinkedBlockingQueue queue = new LinkedBlockingQueue<>();

//Common Thread Pool
ThreadPoolExecutor executorService = new ThreadPoolExecutor(100, 1000,
        0L, TimeUnit.MILLISECONDS, queue, namedThreadFactory);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值