线程---线程池

一、介绍

1.系统启动一个新线程的成本是很高的,因为他涉及与操作系统交互,
尤其需要大量生存期很短暂的线程时,更应该考虑使用线程池
2.【使用线程池可以有效地控制系统并发线程的数量】,当系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃。而线程池的最大线程参数可以控制系统中并发线程数不超过此数
3.过程:
与数据库连接池相似的是,线程池在系统启动时即创建大量空闲的线程
【程序将一个Runnable对象传给线程池(使用excecute()或者submit()),线程池就会启动一个线程来执行他们的run()】;
当run()执行结束后,该线程不会死亡,而是再次返回线程池中成为【空闲状态

4、//TODO

二、面试相关

下面1,2转自https://blog.csdn.net/java_wht/article/details/71700012

1、引入线程池的原因

由于线程的生命周期中包括,创建-就绪-运行-阻塞-挂机-结束 阶段,当我们处理的任务数目比较小的时候,我们可以自己创建几个线程来处理相应的任务,但是有大量的任务时,由于创建和销毁线程都需要很大的开销,运用线程池就可以大大的缓解这些内存开销很大的问题。

2、线程池的使用:

Executor类给我们提供了的静态方法,就可以创建相应的线程池

public static executorService newSigleExecutor();
public static executorService newFixedThredPool();
public static executorService newCachedThreadPool();

1. newCachedThreadPool   创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用他们
2. newFixedThreadPool   创建固定数目的线程池,其中的空闲线程可重用
3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行
4. newSingleThreadExecutor  创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程

具体如下,转 https://blog.csdn.net/QH_JAVA/article/details/54929996

static ExecutorService newFixedThreadPool(int nThreads)

总共创建5个线程 ; 当线程池中的线程处于空闲状态时,会被下一个任务复用

当5个线程都处于活动状态时,再次提交的任务会加入队列,等待其他线程运行结束

static ExecutorService newCachedThreadPool()

可以看出,缓存线程池的大小是 不定值的,可以根据需要创建不同数量的线程。在使用缓存型池时,先查看池中是否有以前创建的线程,如果有就复用如果没有就新建新的线程加入池中线程执行完后可以复用

缓存型池 通常用于执行一些生存期很短的异步型任务

static ExecutorService newSingleThreadExecutor()

从运行结果看,只会创建一个线程,当上一个执行完之后才会执行下一个任务按照指定顺序执行(FIFO,LIFO优先级)执行//TODO

 schedule(Runnable runnable,int dealy,TimeUnit unit)方法来执行指定延迟时间的任务

    ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(5);
    System.out.println(System.currentTimeMillis());
    for(int i =0 ;i <10; i++) {
        Runnable runnable = new Runnable(){
            @Override
            public void run(){
                System.out.println(Thread.currentThread().getName() +"  "+System.currentTimeMillis());
            }
        };
        //添加任务
        executorService.schedule(runnable, 5000, TimeUnit.MILLISECONDS);
    }
 

这个和newFixedThreadPool有点相似,比如会创建固定数目的线程来执行所有任务 ,而且这些线程如果有空闲则会复用;而不同的是newScheduleThreadPool是延迟指定时间后在执行相关任务

4、使用线程池来执行线程任务的步骤

1)使用Excecutor类的静态工厂方法(如上述方法newSingleExcecutor(),newFixedThreadPool(),newCachedThreadPool()),来创建一个ExcecutorService对象,该对象代表一个线程池

2)创建Runnable实现类,作为线程执行的任务

3)调用ExcecutorService对象的submit方法或execute方法提交runnable实例

4)当不想提交任何任务时,调用ExcecutorService对象的shutdown()来关闭线程池

5、相关方法:

shutdown()  会启动线程池的关闭序列,调用shutdown()方法后的线程池不再接受新任务,但会将以前所有已经 提交的任务执行完毕;  当所有的任务都执行完毕后,池中的所有线程死亡 ; 
execute(Runnable x) 开启线程池中的任务 ; 没有返回值。
但无法判断任务是否成功完成
submit(Runnable x)  开启线程池中的任务,返回一个future。
可以用这个future来判断任务是否成功完成

猜你喜欢

转载自blog.csdn.net/qq_24271537/article/details/81635925