Java 线程池的概念及使用

什么是线程池?
等待池是一个存放等待线程的池子,而线程池也就是一个存放线程的池子,我们可以提前创建好一些线程,当我们有任务的时候去线程池里面拿线程来执行任务,任务执行完成之后又放回线程池

为什么要使用线程池?

  • 使用线程池的原因是因为当我们有很多线程的时候,我们频繁的创建和销毁线程会给我们造成很大的资源开销
  • 线程并发数量过多,抢占系统资源从而导致阻塞
  • 方便我们对线程进行管理

线程池
Executor是线程池的顶级接口,Java通过Executors提供了四种线程池,这四种线程池都是直接或间接配置ThreadPoolExecutor的参数实现的。

  • FixedThreadPool() 固定长度的线程池。可以控制线程的最大并发数
  • CachedThreadPool() 可缓存线程池。线程数无限制,即有空闲线程则复用空闲线程,若无空闲线程则新建线程。
  • SingleThreadExecutor() 只有一个线程的单线程池。主要是为了实现串行
  • ScheduledThreadPool() 定时或周期性执行任务的线程池。

创建线程池的时候,上面三个线程池使用ExecutorService接口,并使用Executors实现类来创建一个线程池
创建定时线程池时,使用ScheduledExecutorService接口,并通过new一个ScheduledThreadPoolExecutor实现类来创建

package experiment;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

class Person extends Thread{
    @Override
    public void run() {
        System.out.println("买东西...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
    }
}

public class B {
    public static void main(String[] args) {
        ExecutorService executor= Executors.newFixedThreadPool(3);
        Person person=new Person();
        executor.submit(person);
        executor.submit(person);
    }
}

运行结果如下:
在这里插入图片描述
可以看到我们直接启动了两个线程,需要注意的是,但我们的任务数超过我们线程池里面的长度时,系统会拿出所有的线程来执行任务,执行完成之后会再去执行没有执行的任务

使用定时线程池的时候跟其他的线程池不同

package experiment;

import java.util.concurrent.*;

class Person extends Thread{
    @Override
    public void run() {
        System.out.println("买东西...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
    }
}

public class B {
    public static void main(String[] args) {
        ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
        Person person=new Person();
        sch.schedule(person,2, TimeUnit.SECONDS);
        sch.schedule(person,3, TimeUnit.SECONDS);
    }
}


运行结果:
在这里插入图片描述
任务一是在2s之后运行的,任务二是在3s之后运行的,也就是任务一执行之后的1s之后

schedule的参数:参数一是任务,参数二是延迟时间,参数三是时间单位

另外再说一下就是,当我们的任务都执行完毕的时候,我们的程序并没有结束执行,因为我们的线程池还没有关闭,想要关闭可以使用shutdown() 方法

说一个问题就是,如果我们设定了定时任务,但是我们又关闭了线程池,这个时候其实定时任务仍然会执行

package experiment;

import java.util.concurrent.*;

class Person extends Thread{
    @Override
    public void run() {
        System.out.println("买东西...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
    }
}

public class B {
    public static void main(String[] args) {
        ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
        Person person=new Person();
        sch.schedule(person,2, TimeUnit.SECONDS);
        sch.schedule(person,3, TimeUnit.SECONDS);
        sch.shutdown();
        System.out.println("任务结束");
    }
}

解决方法是使用isTerminated
isTerminted() 调用shutdown关闭线程池后,并且所有的任务都执行完毕后返回true

package experiment;

import java.util.concurrent.*;

class Person extends Thread{
    @Override
    public void run() {
        System.out.println("买东西...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"老板拿来东西...");
    }
}

public class B {
    public static void main(String[] args) {
        ScheduledExecutorService sch=new ScheduledThreadPoolExecutor(3);
        Person person=new Person();
        sch.schedule(person,2, TimeUnit.SECONDS);
        sch.schedule(person,3, TimeUnit.SECONDS);
        sch.shutdown();
        while(sch.isTerminated()){
            System.out.println("任务结束");
        }
    }
}

有任何不对的地方,欢迎联系改正!!!感谢阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答:Java线程池Java中的一个重点知识,并且在Java的工作中经常会遇到,因此在面试中也是必问的面试题目。以下是一些常见的Java线程池面试题: 1. 谈谈什么是线程池? 2. 为什么要使用线程池? 3. 你们哪些地方会使用线程池? 4. 线程池有哪些作用? 5. 线程池的创建方式有哪些? 6. 线程池底层是如何实现复用的? 7. ThreadPoolExecutor核心参数有哪些? 8. 线程池创建的线程会一直在运行状态吗? 9. 为什么阿里巴巴不建议使用Executors? 10. 线程池的底层实现原理是什么? 11. 线程池队列满了,任务会丢失吗? 12. 线程池的拒绝策略类型有哪些? 13. 线程池如何合理配置参数? 这些问题涵盖了线程池的基本概念使用场景、实现原理以及相关的配置和策略等方面的知识。了解这些问题能够帮助面试者更好地理解和应用Java线程池。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [java线程池面试题有哪些?java线程池常见面试题](https://blog.csdn.net/muli525/article/details/123553744)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [(一)【Java精选面试题】线程池底层实现原理(含答案)](https://blog.csdn.net/qq_30999361/article/details/124924343)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值