java线程池介绍

参考:​​​​​​ThreadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别 - 今天代码写完了吗 - 博客园

主线程:

ThreadPoolExecutor threadPoolExecutor = TestThreadPool.getThreadPool();
jzFuture = threadPoolExecutor.submit(new GrOrder(contractnum,orderInfo));
Object obj = jzFuture.get(timeout, TimeUnit.MILLISECONDS); //总超时时间设置

如果主线程超时,则超时后主线程自动向下执行,但线程池中创建的次线程,则需要继续等待response content内容返回,此不会消失,会一直等待,作为活的线程。

其中:

public class GrOrder implements Callable
@Override
public Object call() throws Exception {
       HttpGet httpGet = new HttpGet("http://ip:port/hi")
       String response = httpclient.execute(httpGet);
       return  response ;      //该线程一直等待,不会释放,一直等待结果

}

*****线程池如果不主动关闭,此不会主动关闭,一直运行,故一定要主动关闭线程池。

线程池关闭或停止时,初始化线程池。其中线程池当没有引用且没有剩余线程时会自动关闭

(1)自定义线程池,可以用 ArrayBlockingQueue有界缓存等待队列,让任务在队列排队

int CORE_THREAD_COUNT = 0;
int MAX_THREAD_COUNT = 1840; //17=2*8+1  或者 (40-80)= CPU核心数/(1-阻塞系数)
long KEEP_ALIVE_TIME = 60L;
TimeUnit ALIVE_TIME_UNIT = TimeUnit.SECONDS;
// BlockingQueue<Runnable> queue = new SynchronousQueue<>();
BlockingQueue<Runnable> queue = new ArrayBlockingQueue(1840);
if(executorServer==null||executorServer.isShutdown()||executorServer.isTerminated()){
   synchronized (JzPreCheckUtil.class) {
      if (executorServer==null||executorServer.isShutdown()||executorServer.isTerminated()) {
         executorServer = new ThreadPoolExecutor(CORE_THREAD_COUNT, MAX_THREAD_COUNT, KEEP_ALIVE_TIME, ALIVE_TIME_UNIT, queue);
      }
   }
}

(2)、使用CachedThreadPool创建线程池,无核心线程,最大线程数无界(可能OOM),线程闲置60秒后会销毁线程,SynchronousQueue是个长度为0的阻塞队列,适合任务量大但耗时少的任务。

(3)采用拒绝策略CallerRunsPolicy(完全的同步)让调用该线程池的线程执行操作(异步转同步

(4)动态创建线程池,根据用户数量,动态调整线程池的配置数量,并设置线程数最大值 (无必要,非核心线程有存活时间,同CachedThreadPool)

应用类型包括IO密集型、CPU密集型,IO密集型通常设置为2n+1 (n为CPU核数),CPU密集型通常设置为 n+1,但仅适用于架构;其中生产一般CPU为8核。网上IO密集型类型的应用:线程数 = CPU核心数/(1-阻塞系数),其中,阻塞系数的概念,一般为0.8~0.9之间

c.线程池介绍

i.CachedThreadPool无核心线程,最大线程数无界(可能OOM),线程闲置60秒后会销毁线程,SynchronousQueue是个长度为0的阻塞队列,适合任务量大但耗时少的任务;

//创建使用单个线程的线程池
ExecutorService es1 = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
    es1.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "正在执行任务");
        }
    });
}

ii.fixedThreadPool中核心线程和最大线程相同,LinkedBlockingQueue为无界队列(可能OOM);适用于任务量固定耗时长的任务;

iii.singleThreadPool核心线程和最大线程都为1,表示同一时刻最多只会有一个线程。适用于多个任务顺序使用的场景

通过对ThreadPoolExecutor类分析,引发java.util.concurrent.RejectedExecutionException主要有两种原因:

线程池显示的调用了shutdown()之后,再向线程池提交任务的时候,如果你配置的拒绝策略是ThreadPoolExecutor.AbortPolicy的话,这个异常就被会抛出来。
当你的排队策略为有界队列,并且配置的拒绝策略是ThreadPoolExecutor.AbortPolicy,当线程池的线程数量已经达到了maximumPoolSize的时候,你再向它提交任务,就会抛出ThreadPoolExecutor.AbortPolicy异常。

IV .ScheduledThreadPool核心线程数为用户自定义,最大线程数无限制,非核心线程数一空闲立刻销毁。队列采用了一个可对任务按延时时间进行排序的队列,延时时间越短排在最前。这也是个无界队列。这种线程池适合固定周期的定时任务或重复任务。但无界的队列和无限制的最大线程数,意味着它会出现内存溢出和cpu占用率百分百的问题;

d.SynchronousQueue 、 LinkedBlockingQueue 和 ArrayBlockingQueue 区别

i.SynchronousQueue没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素。拥有公平(FIFO)和非公平(LIFO)策略,非公平侧罗会导致一些数据永远无法被消费的情况。使用SynchronousQueue阻塞队列一般要求maximumPoolSizes为无界(Integer.MAX_VALUE),避免线程拒绝执行操作。

ii.LinkedBlockingQueue是一个无界缓存等待队列。当前执行的线程数量达到corePoolSize的数量时,剩余的元素会在阻塞队列里等待,当队列满时,才会开启新的线程,立即执行新添加的任务,当线程数达到 maximumPoolSize 数量时,执行线程拒绝策略。每个线程完全独立于其他线程。生产者和消费者使用独立的锁来控制数据的同步,即在高并发的情况下可以并行操作队列中的数据。

iii. ArrayBlockingQueue是一个有界缓存等待队列,可以指定缓存队列的大小,当正在执行的线程数等于corePoolSize时,多余的元素缓存在ArrayBlockingQueue队列中等待有空闲的线程时继续执行,当ArrayBlockingQueue已满时,加入ArrayBlockingQueue失败,会开启新的线程去执行,当线程数已经达到最大的maximumPoolSizes时,再有新的元素尝试加入ArrayBlockingQueue时会执行拒绝策略。

(4)拒绝策略

AbortPolicy:默认策略,丢弃当前被拒绝的任务,抛出RejectedExecutionException异常。

DiscardPolicy: 这个拒绝策略就是丢弃当前被拒绝的任务,不抛出异常;

DiscardOldestPolicy: 这个拒绝策略就是将最先进入工作队列等待的任务丢弃,然后接受新的任务

CallerRunsPolicy: 这个拒绝策略就是谁调用了本线程池,则谁来执行该任务,保证的任务不会丢失。

(5)线程池当没有引用且没有剩余线程时会自动关闭


ThreadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

shutdown()

将线程池状态置为SHUTDOWN,并不会立即停止:

  1. 停止接收外部submit的任务
  2. 内部正在跑的任务和队列里等待的任务,会执行完
  3. 等到第二步完成后,才真正停止

shutdownNow()

将线程池状态置为STOP。企图立即停止,事实上不一定:

  1. 跟shutdown()一样,先停止接收外部提交的任务
  2. 忽略队列里等待的任务
  3. 尝试将正在跑的任务interrupt中断
  4. 返回未执行的任务列表

awaitTermination(long timeOut, TimeUnit unit)

当前线程阻塞,直到

  1. 等所有已提交的任务(包括正在跑的和队列中等待的)执行完
  2. 或者等超时时间到
  3. 或者线程被中断,抛出InterruptedException
    然后返回true(shutdown请求后所有任务执行完毕)或false(已超时)

shutdown()和awaitTermination()的区别

  1. shutdown()后,不能再提交新的任务进去;但是awaitTermination()后,可以继续提交。
  2. awaitTermination()是阻塞的,返回结果是线程池是否已停止(true/false);shutdown()不阻塞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值