java使用线程池创建线程_线程池创建后怎么调用

java使用线程池创建线程_线程池创建后怎么调用第一种方式:lambda构建方式为:运行后第二种,仿照源码的方式创建:可以参考源码中默认工厂的创建方式,查看路径如下:进入再进入new的类可见自己创建一个工厂时需要实现ThreadFactory的接口做部分解读如下:=

构建函数的参数说明

JAVA 创建线程池七个参数作用及学习总结

手动创建示例

依旧是在 main 方法中做示例

1.全参构造

定义如下:
注意这个是在方法外定义 为了多个方法使用同一个线程池以免浪费,由于我是在 main中做测试故需要定义为 static,一般使用时如果放在 spring InitializingBean 或其他初始话动作中的话 不必添加 static,如果在静态代码块中初始化则需要 static

private static ThreadPoolExecutor threadPoolExecutor = null;

main 中做初始化以及使用

threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(500),  Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
                
threadPoolExecutor.submit(new BusinessThread(5));
threadPoolExecutor.shutdown();

简单解读
这里 第一行的第一个构建参数即为核心线程数(这里我设置的10),即使空闲不在使用中也不会销毁,除非设置了核心线程超时时间的参数 即allowCoreThreadTimeOut 核心线程数即这个线程池的最小线程数。

第一行第二个构建参数,即最大线程数 当核心线程数中的所有线程没有空闲时,再提交任务时会进入工作队列等待,当工作队列也满了时,会再次创建一个新的线程,并从工作队列的首部取出一个任务交给新创建的线程去执行,新来的任务则进入工作队列,插入队尾(相当于排队等待),但通过这样的方式创建的线程是存在上限的,最大线程数就是这个上限。当最大线程数也上限了怎么办?继续往下看,JDK 也给了相应的几种解决策略供使用。

第一行第三个构建参数,第四个构建参数,即空闲线程等待时间,等待时间的单位,这里空闲线程指的并不是核心线程,而是上面通过最大线程数的方式,由于工作队列以及核心线程数均满时额外创建的线程,当这些线程空闲下来时,并等待到了指定的时间时依旧没有被使用,那么这些线程会被销毁。

第一行第五个构建参数,即 工作队列的类型以及队列的大小,目前提供四种工作队列,这里我简单说,详细见最上方参数链接

ArrayBlockingQueue
有界阻塞队列,先进先出,新任务会放到队尾就是最后。核心线程没有空闲时,提交新任务则会放入队列的队尾,等待。
如果队列已满,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。

LinkedBlockingQuene
无界阻塞队列(其实最大容量为Interger.MAX),先进先出。由于该队列的近似无界性(即没有上限),核心线程没有空闲时提交新任务会一直存入该队列,而不去创建新线程直到达到最大线程数,因此使用该工作队列时,参数 maxPoolSize 其实无用。

SynchronousQuene
不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。
也就是说新任务进来时不会缓存,直接执行该任务,如果没有可用线程则创建新线程,如果线程数量达到 maxPoolSize,则执行拒绝策略。

PriorityBlockingQueue
具有优先级的无界阻塞队列,优先级通过参数Comparator实现。

第一行第六个构建参数,即构建新线程的方式,一般使用默认的 factory(工厂)制造线程即可,一般是对当前线程做一些命名以及是否守护线程的属性赋值。如果有自己的需求可以参考源码的方式创建一个简单的 ThreadFactory ,下面一会儿会有一些例子提供参考。这里我使用的JDK 里面提供的默认创建方式,一般也够用了。

第一行第七个构建参数,即拒绝策略,上面队列中一再说明了,当核心已满,队列已满,最大线程数也满的情况下会执行的拒绝策略,简单来说就是当定义的线程池已经没有能力处理新的任务时,再有新的任务提交时该怎么去处理,JDK 同样提供了四种拒绝策略:

CallerRunsPolicy
在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务
这里调用者指的是提交任务的线程,即执行提交任务代码当时所在的线程。

AbortPolicy
丢弃,并抛出RejectedExecutionException异常,一般提供的已有线程池大多都会选择这一种

DiscardPolicy
直接丢弃,什么都不做

DiscardOldestPolicy
抛弃进入队列最早的任务,然后尝试把这次拒绝的任务加入队列

第二行
提交一个线程任务,这里 new 的类为自定义的类,并使用了改类的某一个构造函数,该类继承 thread,或者 实现 runnable ,提交到线程池种会执行 重写的 run 方法的内容。

第三行
关闭当前线程池,会等待已有任务的执行完成,但是新的任务无法再提交。

其它构造方法

在这里插入图片描述
这里JDK 是 1.8版本;
可见JDK 提供的构造函数包括最后一个全参构造一共有四种
第一种舍弃了线程构建以及拒绝策略,
第二种舍弃了拒绝策略,
第三种线程构造,

第一种
可见 舍弃的线程构造以及拒绝策略均采用了默认的方式
在这里插入图片描述
而拒绝策略默认为
abort 直接丢弃并抛异常
在这里插入图片描述
第二种
类似的使用了默认的拒绝策略
在这里插入图片描述
第三种
类似的使用了默认的线程构造
在这里插入图片描述

定义线程构建方式(名称或否守护线程)ThreadFactory

第一种方式
lambda

threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(500),
                r->new Thread(r, "my-taskPoolThreadA-"+r.hashCode()) , new ThreadPoolExecutor.CallerRunsPolicy());

构建方式为:
r->new Thread(r, “my-taskPoolThreadA-”+r.hashCode())

运行后
在这里插入图片描述
第二种,仿照源码的方式创建:
可以参考源码中默认工厂的创建方式,查看路径如下:
在这里插入图片描述
进入
在这里插入图片描述
再进入 new 的类
在这里插入图片描述
可见自己创建一个工厂时需要实现 ThreadFactory 的接口

做部分解读如下:
在这里插入图片描述
实际自己构造时完全可以先照搬下来只改改命名方式:

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadFactory implements ThreadFactory { 
   

    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    MyThreadFactory() { 
   
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        namePrefix = "my-pool-" +
                poolNumber.getAndIncrement() +
                "-thread-";
    }

    @Override
    public Thread newThread(Runnable r) { 
   
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

实际上我们完全可以根据自己的需要决定是否设置保护线程,即 重写的方法中 newThread(Runnable r) 中 内部属性我们可以通过我们设定的其他值来控制,可以整改添加一些构造函数,将一些我们想要的控制项通过构造方法或者其他方法的方式传入Factory 并在重写的方法内生效,使之得到应用。
例如可以如下修改:

为了外部调用构造函数定义为 public

public class MyThreadFactory implements ThreadFactory { 
   

    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;
    private boolean nDaemon;

    public MyThreadFactory() { 
   
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        namePrefix = "my-pool-" +
                poolNumber.getAndIncrement() +
                "-thread-";
    }

    public MyThreadFactory(String prefix, boolean needDaemon){ 
   
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();

        namePrefix = prefix + "-mythread-" + poolNumber.getAndIncrement();

        nDaemon = needDaemon;
    }

    @Override
    public Thread newThread(Runnable r) { 
   
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0);
        if (nDaemon)
            t.setDaemon(nDaemon);

        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

如此一来可以在外部如下书写:

        threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(500),
                new MyThreadFactory("ACCName", false), new ThreadPoolExecutor.CallerRunsPolicy());

今天的文章java使用线程池创建线程_线程池创建后怎么调用分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/86687.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注