学习
实践
活动
工具
TVP
写文章

写给小白看的线程池,还有10道面试题

因此,长时间保持空闲的线程不会使用任何资源。 newScheduledThreadPool 创建一个数量固定的线程池,支持执行定时性或周期性任务。 newSingleThreadExecutor 创建一个线程线程池。这个线程池只有一个线程工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个线程来替代它。 "); }); } } 以上程序执行结果如下: 提交任务0 提交任务1 提交任务2 可以看出,shutdown() 之后就不会再接受的任务了,不过之前的任务会被执行完成。 面试题9:了解线程池状态? 通过获取线程池状态,可以判断线程池是否是运行状态、可否添加的任务以及优雅地关闭线程池等。 ? RUNNING:线程池的初始化状态,可以添加待执行的任务。 线程池将线程和任务进行解耦,线程线程,任务是任务,摆脱了之前通过 Thread 创建线程时的一个线程必须对应一个任务的限制。

20220

Java异步编程——深入源码分析FutureTask

Java的异步编程是一项非常常用的多线程技术。 之前通过源码详细分析了ThreadPoolExecutor《你真的懂ThreadPoolExecutor线程池技术?看了源码你会有全新的认识》。 通过创建一个ThreadPoolExecutor,往里面丢任务就可以实现多线程异步执行了。 但之前的任务主要倾向于线程池,并没有讲到异步编程方面的内容。 回顾这个Demo做了什么, 构建了一个线程池 往线程池里面丢两个需要执行的任务 最后获取这两个任务的结果 其中第二点是异步执行两个任务,这两个任务和主线程分别是用了三个线程并发执行的,第三点是线程中同步等待两个任务的结果 如果看过之前写的《你真的懂ThreadPoolExecutor线程池技术?看了源码你会有全新的认识》,应该了解ThreadPoolExecutor执行任务是可以调用execute()方法的。 但这样并没有异步的效果,因为没有启用线程去跑,而是原来的线程阻塞执行的。

30030
  • 广告
    关闭

    2022腾讯全球数字生态大会

    11月30-12月1日,邀您一起“数实创新,产业共进”!

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    java线程池,阿里为什么不允许使用Executors?

    线程池可以通过池看出来是一个资源集,任何池的作用都大同小异,主要是用来减少资源创建、初始化的系统开销。 创建线程很“贵”? 是的。创建线程的代价是昂贵的。 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个线程。 newSingleThreadExecutor (ThreadPoolExecutor)创建一个线程线程池。这个线程池只有一个线程工作,也就是相当于单线程串行执行所有任务。 如果这个唯一的线程因为异常结束,那么会有一个线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。 最后 关于 ThreadPoolExecutor 的逻辑实际使用的时候会有点奇怪,因为线程池中的线程并没有超过最大线程数,有没有一种可能当任务被堵塞很久的时候创建线程池来处理呢?

    63020

    快速掌握并发编程---线程池的原理和实战

    (并不是每个系统都会使用消息队列之类的第三方框架),所以,针对上面的举例场景,如果没有线程池的说法,将会: 发站内信启动一个线程,发完结束线程。发个短信启动一个线程,发完结束线程。 发个推送启动一个线程,发完结束线程…. 有没有发现,我们会不断的启动线程、销毁线程。 说到这里,有人要说了线程不是携带资源的最小单位,操作系统的书籍中还给我们说了线程之间的切换消耗很小线程池将线程和任务进行解耦,线程线程,任务是任务,摆脱了之前通过 Thread 创建线程时的一个线程必须对应一个任务的限制。 在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行。 SynchronousQueue 是一个没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加的元素。

    18210

    ThreadPoolExcutor源码分析

    ThreadPoolExecutor的状态和属性 ThreadPoolExecutor线程池有5个状态,分别是: RUNNING:可以接受的任务,也可以处理阻塞队列里的任务 SHUTDOWN:不接受的任务 状态和线程ThreadPoolExecutor内部使用一个整型变量保存,没错,一个变量表示两种含义 为什么一个整型变量既可以保存状态,又可以保存数量? 调用execute方法之前,使用FutureTask包装一个Runnable,这个FutureTask就是返回值。 ThreadPoolExecutor的关闭 线程池的启动过程分析好了之后,接下来看线程池的关闭操作: shutdown方法,关闭线程池,关闭之后阻塞队列里的任务不受影响,会继续被Worker处理,但是的任务不会被接受 但是shutdownNow方法不一样,它会把线程池状态改成STOP状态,这样不会处理阻塞队列里的任务,也不会处理的任务: // shutdownNow方法会有返回值的,返回的是一个任务列表,而shutdown

    19120

    一个 Java 线程池bug引发的 GC 机制思考

    A@1be6f5c3 从结果上看,finalize方法都没有执行(因为main方法执行完成后进程直接结束了),更不会出现提前finalize的问题了 基于上面的测试结果,再测试一种情况,循环之前先将对象 猜测可能是由于execute方法中,会调用threadPoolExecutor,会创建并启动一个线程,这时会发生一次主动的线程切换,导致活动线程中对象不可达 结合上面Oracle Jdk文档中的描述 void run() { } }).start(); //模拟ThreadPoolExecutor启动新建线程后,循环检查线程池状态,验证是否会在 [true] 从错误上来看,“线程池”同样被提前shutdown了,那么一定是由于新建线程导致的? e) { e.printStackTrace(); } //模拟ThreadPoolExecutor启动新建线程后,循环检查线程池状态,验证是否会在finalize中

    29010

    线程池实现原理-1

    ,不然程序永远不会结束 executorService.shutdown(); } } 这个看起来好像没有用到线程池,其实是因为没有可复用的线程,所以就一直创建线程了 public corePoolSize,保持存活的工作线程的最小数目,当小于corePoolSize时,会直接启动一个线程来处理任务,而不管线程池中是否有空闲线程 keepAliveTime是空闲线程的存活时间, 没满,创建一个工作线程来执行任务。满了,则进入下个流程。 其次线程池判断工作队列是否已满?没满,则将提交的任务存储工作队列里。满了,则进入下个流程。 最后线程池判断整个线程池是否已满(即线程数是否小于线程池最大容量)?没满,则创建一个的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。 ? ,结果它就被放到阻塞队列中了,然后核心线程都执行完了(并且都被销毁了),如果不调用一下这个方法,则放到阻塞队列中的任务就不会被执行 核心线程不是一直都存在的

    45610

    线程池是如何重复利用空闲的线程来执行任务的?

    Java开发中,经常需要创建线程去执行一些任务,实现起来也非常方便,但如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间 ,如果有新任务来,就不会创建的核心线程。 事实上,复用机制跟线程池的阻塞队列有很大关系,我们可以看到,execute核心线程满了,但是队列不满的时候会把任务加入到队列中,一旦加入成功,之前被阻塞的线程就会被唤醒去执行的任务,这样就不会重新创建线程我们这个例子中,由于队列是无界的,所以始终不会执行到execute的第三部分即启动非核心线程,假如我们设置队列为有界的,那么必然就会执行到这里了。 那些被销毁的线程是随机的,可能是第一个创建的线程,也可能是最后一个创建的线程,或其它时候创建的线程

    26120

    一个 JDK 线程池 BUG 引发的 GC 机制思考

    A@1be6f5c3 从结果上看,finalize方法都没有执行(因为main方法执行完成后进程直接结束了),更不会出现提前finalize的问题了 基于上面的测试结果,再测试一种情况,循环之前先将对象 猜测可能是由于execute方法中,会调用threadPoolExecutor,会创建并启动一个线程,这时会发生一次主动的线程切换,导致活动线程中对象不可达 结合上面Oracle Jdk文档中的描述 void run() { } }).start(); //模拟ThreadPoolExecutor启动新建线程后,循环检查线程池状态,验证是否会在 [true] 从错误上来看,“线程池”同样被提前shutdown了,那么一定是由于新建线程导致的? e) { e.printStackTrace(); } //模拟ThreadPoolExecutor启动新建线程后,循环检查线程池状态,验证是否会在finalize中

    16320

    深度解读Java线程池思想及实现

    友情提醒:本文略长,建议PC上阅读,边看文章边翻源码效果更佳,建议想好好看的读者抽出至少30分钟的整块时间来阅读。如果仅为面试需要可直接跳到文章最后总结部分。 { @Override public void execute(Runnable r) { // 这里不是用的new Thread(r).start(),也就是说没有启动任何一个线程 r.run(); } } 希望每个任务提交进来后,直接启动一个线程来执行这个任务,可以这么实现: class ThreadPerTaskExecutor implements ,之前说了,Worker的构造方法会调用 ThreadFactory 来创建一个线程 final Thread t = w.thread; if (t 如果某个任务执行出现异常,那么执行任务的线程会被关闭,而不是继续接收其他任务。然后会启动一个线程来代替它。 什么时候会执行拒绝策略?

    33450

    Java多线程并发编程一览笔录

    5、线程间的关系? 某线程a 中启动另外一个线程 t,那么我们称 线程 t是 线程a 的一个线程,而 线程a 是 线程t 的 父线程。 最典型的就是我们main方法中 启动 一个 线程去执行。 (2)作为结束信号:通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直入口处等待。 用 N 初始化的 CountDownLatch 可以使一个线程 N 个线程完成某项操作之前一直等待,或者使其某项操作完成 N 次之前一直等待。 */ try { task.run(); } finally { doneSignal.countDown();/** doneSignal 计数减一,直到最后一个线程结束 这个线程池只有一个线程工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

    38920

    CTO 说了,再发现谁用 kill -9 关闭程序就开除!

    第一步:停止接收请求和内部线程 第二步:判断是否有线程正在执行 第三步:等待正在执行的线程执行完毕 第四步:停止容器 以上四步才是正常的结束流程,那springboot怎么正常结束服务呢? kill -15 pid来结束这个进程,你们猜 test — end会被打印? jvm注册了一个关闭钩子,我们执行colse方法的时候会删除这个关闭钩子,jvm就会知道这是需要停止服务。 interrupt方法,导致sleep报错,这三种方式都可以比较优雅的停止springboot服务,如果我项目中存在线程休眠,我希望10秒以后再停止服务可以? 其实很简单在你要执行的方法上添加一个注解即可:@PreDestroy Destroy:消灭、毁灭 pre:前缀缩写 所以合在一起的意思就是容器停止之前执行一次,你可以在这里面做备份操作,也可以做记录停机时间等

    8530

    Java多线程并发编程一览笔录

    5、线程间的关系? 某线程a 中启动另外一个线程 t,那么我们称 线程 t是 线程a 的一个线程,而 线程a 是 线程t 的 父线程。 最典型的就是我们main方法中 启动 一个 线程去执行。 (2)作为结束信号:通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直入口处等待。 用 N 初始化的 CountDownLatch 可以使一个线程 N 个线程完成某项操作之前一直等待,或者使其某项操作完成 N 次之前一直等待。 */ try { task.run(); } finally { doneSignal.countDown();/** doneSignal 计数减一,直到最后一个线程结束 这个线程池只有一个线程工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

    534100

    Java多线程面试题-可能学了个寂寞?

    系统运行一个程序即是从一个进程从创建、运行到消亡的过程。Java中,当我们启动main函数时其实就是启动一个JVM的进程,而mian函数所在的线程就是这个进程中的一个线程,称为主线程。 换句话说,当前任务执行完CPU时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换会这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。 当我们new一个Thread时,线程进入了新建状态,调用start()方法,会启动一个线程并使线程进入就绪状态,等分到时间片后就可以开始运行了。 当有一个的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。 keepAliveTime:当线程池中的线程数量⼤于 corePoolSize 的时候,如果这时没有的任务提交,核⼼线程外的线程不会⽴即销毁,⽽是会等待,直到等待的时间超过了keepAliveTime

    12220

    Java并发指南12:深度解读 java 线程池设计思想及源码实现

    Executor { public void execute(Runnable r) { r.run();// 这里不是用的new Thread(r).start(),也就是说没有启动任何一个线程 } } 我们希望每个任务提交进来后,直接启动一个线程来执行这个任务,我们可以这么实现: class ThreadPerTaskExecutor implements Executor { 这个方法非常重要 addWorker(Runnable firstTask, boolean core) 方法,我们看看它是怎么创建线程的: // 第一个参数是准备提交给这个线程执行的任务,之前说了 ,之前说了,Worker的构造方法会调用 ThreadFactory 来创建一个线程 final Thread t = w.thread; if (t ! 然后会启动一个线程来代替它。 什么时候会执行拒绝策略?

    20410

    java线程池详解

    启动8个线程,其中第一个是1s执行完毕,其余都是2s执行完毕, service.execute(new R(1000)); // 有一个任务会进行等待,当第一个执行完毕后 ,会再次偷取最后一个任务执行 for (int i = 0; i 运行这段代码,我们看到如下效果,发现第一个线程执行完毕后,会从线程池中再拿出一个线程执行 五种线程池的适应场景 newScheduledThreadPool:可以延时启动,定时启动线程池,适用于需要多个后台线程执行周期任务的场景。 后,就不会再增加了;若后续有的任务加入,则直接进入队列等待,当使用这种任务队列模式时,一定要注意你任务提交与处理之间的协调与控制,不然会出现队列中的任务由于无法及时处理导致一直增长,直到最后资源耗尽的问题 最后再用一个线程池的执行流程图结束本篇内容,感谢观看 本文为从大数据到人工智能博主「jellyfin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

    11910

    关于线程池的面试,看这篇就够了!

    Executor { public void execute(Runnable r) { r.run();// 这里不是用的new Thread(r).start(),也就是说没有启动任何一个线程 } } 我们希望每个任务提交进来后,直接启动一个线程来执行这个任务,我们可以这么实现: class ThreadPerTaskExecutor implements Executor { 这个方法非常重要 addWorker(Runnable firstTask, boolean core) 方法,我们看看它是怎么创建线程的: // 第一个参数是准备提交给这个线程执行的任务,之前说了 ,之前说了,Worker的构造方法会调用 ThreadFactory 来创建一个线程 final Thread t = w.thread; if (t ! 然后会启动一个线程来代替它。 ” 什么时候会执行拒绝策略?

    27640

    全面理解:Android中的线程线程

    所以可以UI线程使用handler发送任务到HandlerThread中执行,且可以随意多次发送任务。(而普通thread执行完run方法中的耗时操作就结束了。) 使用场景:如果同时有多个服务启动请求发送到onStartCommand(),不应该在处理完一个请求后调用stopSelf();因为调用此函数销毁service之前,可能service又接收到启动请求 然后不间断连续启动3次,由日志可见是顺序执行的,最后都执行完才走到onDestroy。 ThreadPoolExecutor执行任务的执行规则 如下: 如果线程池中的线程数未到达核心线程数,那么会直接启动一个核心线程来执行这个任务。 固定的核心线程数量,没有非核心线程,空闲时不会被回收,队列长度无限制。因为不会被回收,所以能快速执行外界请求。

    28010

    【愚公系列】2022年01月 Java教学课程 62-异步之线程

    那么此时才是真正的JVM进程中创建了一个线程线程一经启动并不是立即得到执行,线程的运行与否要听令与CPU的调度,那么我们把这个中间状态称之为可执行状态(RUNNABLE)也就是说它具备执行的资格,但是并没有真正的执行起来而是等待 例如:因为wait()而等待的线程正在等待另一个线程去调用notify()或notifyAll();一个因为join()而等待的线程正在等待另一个线程结束。 ("1.通过new初始化一个线程,但是还没有start()之前线程的状态:" + thread.getState()); //启动线程 thread.start(); ("1.通过new初始化一个线程,但是还没有start()之前线程的状态:" + thread1.getState()); //启动线程 thread1.start( 针对这一种情况,为了提高性能,我们就可以采用线程池。线程启动的时,会创建大量空闲线程,当我们向线程池提交任务的时,线程池就 ​ 会启动一个线程来执行该任务。

    5510

    扫码关注腾讯云开发者

    领取腾讯云代金券