首页 > 其他分享 >线程池

线程池

时间:2022-09-24 01:12:19浏览次数:53  
标签:int number 线程 executor new public

Java内置线程池

线程池有几个核心参数:1、核心线程数 2、最大线程数 3、阻塞队列

1、线程池创建时,不会创建线程。

2、当有任务到来时,如果当前执行线程数少于核心线程数,会创建线程执行,不管是否有其它线程正在执行。

3、如果当前执行线程数等于核心线程数,新来的线程会进入阻塞队列。

4、如果阻塞队列已经满了,而且当前线程数小于核心线程数,会开启新线程先执行执行新到来的任务,当其它线程执行完毕时会从阻塞队列中取出任务执行。

5、如果当前正在执行的线程等于最大线程数,且阻塞队列已满则会执行拒绝策略。

对于第二点,测试代码如下:

public class ThreadPoolTest implements Runnable {

    private int number;

    public ThreadPoolTest(int number){
        this.number = number;
    }

    public void run() {
        try {
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

        // 当前执行线程数0
        System.out.println("当前执行线程数:"+executor.getActiveCount());

        int i = 0;
        executor.submit(new ThreadPoolTest(i));

      	// 等待第一个线程执行完毕
        Thread.sleep(1000);

        i++;
        executor.submit(new ThreadPoolTest(i));

        Thread.sleep(100000);
        executor.shutdown();
    }
}

对于第三点,测试代码如下:

public class ThreadPoolTest implements Runnable {

    private int number;

    public ThreadPoolTest(int number){
        this.number = number;
    }

    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

        // 当前执行线程数0
        System.out.println("当前执行线程数:"+executor.getActiveCount());

        int i = 0;
        for (; i < 3; i++) {
            executor.submit(new ThreadPoolTest(i));
        }

        Thread.sleep(100000);
        executor.shutdown();
    }
}

对于第四点,测试代码如下:

public class ThreadPoolTest implements Runnable {

    private int number;

    public ThreadPoolTest(int number){
        this.number = number;
    }

    public void run() {
        try {
            Thread.sleep(5500);
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

        // 当前执行线程数0
        System.out.println("当前执行线程数:"+executor.getActiveCount());

        int i = 0;
        for (; i < 4; i++) {
            executor.submit(new ThreadPoolTest(i));
        }
    }
}

对于第五点,测试代码如下:

public class ThreadPoolTest implements Runnable {

    private int number;

    public ThreadPoolTest(int number){
        this.number = number;
    }

    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

        // 当前执行线程数0
        System.out.println("当前执行线程数:"+executor.getActiveCount());

        int i = 0;
        for (; i < 6; i++) {
            executor.submit(new ThreadPoolTest(i));
        }

        Thread.sleep(100000);
        executor.shutdown();
    }
}

Tomcat线程池

Tomcat线程池类是:org.apache.tomcat.util.threads.ThreadPoolExecutor

跑上面的测试代码,会发现和Java的线程池存在不同,主要体现在第3,4,5点上关于阻塞队列。

Tomcat的线程池在当前执行线程数量不超过最大线程数量时,会直接开启新线程执行,只有当线程数等于最大线程数量时,才会将请求进行排队,等到队列满了的时候,会执行拒绝策略。

对于Java内置线程的改动主要体现在TaskQueue队列上,默认的Java线程池在核心线程满了之后会将任务放在阻塞队列上,Tomcat线程池继承拓展了Java线程池,并提供了TaskQueue的阻塞队列实现,重写了队列的offer方法,在判断当前线程数小于最大线程数时,offer方法会返回false,导致默认的Java线程池去创建新的线程执行任务。

代码如下:

// java.util.concurrent.ThreadPoolExecutor
public void execute(Runnable command) {
  // 省略部分代码
  // 主要看下面的if中workQueue.offer(command),当前线程数小于最大线程数时,这里返回了false
  if (isRunning(c) && workQueue.offer(command)) {
    int recheck = ctl.get();
    if (! isRunning(recheck) && remove(command))
      reject(command);
    else if (workerCountOf(recheck) == 0)
      addWorker(null, false);
  }
  else if (!addWorker(command, false))
    reject(command);
}

// org.apache.tomcat.util.threads.TaskQueue
public boolean offer(Runnable o) {
  // 省略部分代码
  
  // 主要是这里,这里的parent是线程池对象,创建队列时tomcat注入了线程池对象
  //if we have less threads than maximum force creation of a new thread
  if (parent.getPoolSize()<parent.getMaximumPoolSize()) {
    return false;
  }
  //if we reached here, we need to add it to the queue
  return super.offer(o);
}

标签:int,number,线程,executor,new,public
From: https://www.cnblogs.com/zanpocc/p/16724794.html

相关文章

  • 进程与线程
     程序的概念:程序是指令和数据的有序集合,其本身没有任何运行的含义,程序是静态的。什么是进程?进程是程序在处理器上的一次执行过程,它是一个动态的概念。进程是......
  • C#中使用Invoke和BeginInvoke跨线程更新UI控件示例代码
    在多线程开发过程中,有时候需要更新UI控件内容,但是在c#多线程Task、Thread、BackgroundWork中不能直接更新UI控件,否则会报调用线程不能访问此对象,因为它由另一个线程拥有The......
  • Java线程-02
    Java8-- 0、前言一年前写了一篇“Java线程-01”,只是没学透彻。现在继续。ben发布于博客园比如,怎么配置线程池的线程名称、设置拒绝策略、使用ScheduledThreadPoolE......
  • qt 线程的创建和退出
    qt常用的线程创建有两种方法,一种是继承QThread,重写run函数,一种是创建一个业务处理类,moveToThread。我创建了一个widget工程,演示一下。示例地址:https://files-cdn.cnblogs......
  • 对多线程原子性的理解
    多线程原子性的理解:一个操作要么全部执行完毕,不会受到干扰而被中断;要么全都不执行。对于多线程中操作共享变量的操作,要保证它的原子性。在一个类中有共享变量count,开启......
  • 一种简单的springboot启动后启动一条死循环线程方式
    前言之前有测试#启动类加@EnableAsync#方法上加@Async@PostConstruct但是依旧会卡主主线程,所有另辟蹊径在启动类上加@EnableAsync新建一个类,实现Applicatio......
  • JAVA 绑定线程到指定CPU上
    CPU个数、核数、线程数、JAVA多线程关系cpu个数、核数、线程数的关系cpu个数:是指物理上,也及硬件上的核心数;核数:是逻辑上的,简单理解为逻辑上模拟出的核心数;线程数:是同一......
  • JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport
    一、前言在多线程的场景下,我们会经常使用加锁,来保证线程安全。如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题。也可以使用Condition的aw......
  • Day8 多线程基础概念的学习
    Day8多线程学习多线程多任务任务就是需要完成的一件事,多任务可能在同一时间解决,或者按步一个一个解决。通过多条道路解决原来一条道路堵塞的问题,多线程。就是同一时......
  • Java多线程
    多线程详解(Java.Thread)线程简介线程实现(重点)线程状态线程同步(重点)线程通信问题高级主题多任务:现实中太多这样同时做多件事情的例子了,看起来是多个任务都在做,其实本......