多线程学习笔记:2.使用线程池技术实现多线程一。

参考文档:https://blog.csdn.net/wang7807564/article/details/80048648

                  https://blog.csdn.net/he90227/article/details/52576452

线程池的技术背景

在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。

所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些”池化资源”技术产生的原因。

线程池就是为了减少创建和销毁线程时的时间,提高效率。

线程池框架结构:

c6e8878b385f63044ccf27e10b577fbb.jpg (737Ã659)

Executor:是一个执行器接口,有一个executor方法。

public interface Executor {
    void execute(Runnable command);
}

 ExecutorService是Executor的子接口,并补充了一些自己的方法。 

submit(Runnable)和execute(Runnable)区别是前者可以返回一个Future对象,通过返回的Future对象,我们可以检查提交的任务是否执行完毕等。 
submit(Callable)和submit(Runnable)类似,也会返回一个Future对象,但是除此之外,submit(Callable)接收的是一个Callable的实现,Callable接口中的call()方法有一个返回值,可以返回任务的执行结果,而Runnable接口中的run()方法是void修饰的,没有返回值。 
shutdown() 
对当前线程池中已经执行的线程下达关闭命令,同时拒绝在线程池中添加新的任务,如果使用submit()添加新的任务,会产生RejectedExecutionException的异常。

shutdownNow()  

试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
isShutdown() 
如果这个excutor()已经被下达关闭指令,则返回真,但是具体是否真的被关闭了,需要用isTerminated()方法来判断。 
isTerminated() 
如果所有任务已经完成后续的关闭工作则返回真。

ScheduledExecutorService:定时任务执行器

Runnable/Callable为运行任务,long为延迟时间,TimeUnit为时间单位

ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,当延迟度时间小于任务执行时间时,延迟时间失效,会在任务结束后立马开始新任务。

ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,

由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。

Executors:
是一个静态工厂类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService 接口。

常用线程池:

SingleThreadExecutor:单个后台线程 (其缓冲队列是无界的),每次只有一个线程再执行。

创建一个单线程的线程池。这个线程池只有一个核心线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

FixedThreadPool:只有核心线程的线程池,大小固定 (其缓冲队列是无界的) 。

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

一般设置为与cpu数量相同;获取cpu的数量:

int cpuNums = Runtime.getRuntime().availableProcessors();

CachedThreadPool:无界线程池,可以进行自动线程回收。官方推荐使用

如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。SynchronousQueue是一个是缓冲区为1的阻塞队列。

ScheduledThreadPool:核心线程池固定,大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

创建一个周期性执行任务的线程池。如果闲置,非核心线程池会在DEFAULT_KEEPALIVEMILLIS时间内回收。

线程池使用步骤:

1.创建线程池

2.创建任务对象

3.调用启动线程方法

4.关闭线程池

public class ThreadPoolDemo {
    public static void main(String[] args) {
        //1
        ExecutorService exec = Executors.newCachedThreadPool();
        //2
        RunnableTest run = new RunnableTest();
        //3
        exec.execute(run);
        //4
        exec.shutdown();
    }
}
class RunnableTest implements Runnable{

    @Override
    public void run() {
        System.out.println("RunnableTest Run");
    }
}


 

 

猜你喜欢

转载自blog.csdn.net/qq_42283110/article/details/86586311