java-线程池

Runnable对比Callable:
Runable不会返回结果或抛出检查异常,但是Callable可以。(Executors能够实现二者转换)
execut()对比submit():
execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;
submit()方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功,并且可以通过 Future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
shutdown()对比shutdownNow():
shutdown():关闭线程池,线程池的状态变为SHUTDOWN。线程池不再接收新任务,但是需要等待队列中的任务执行完毕。
shutdownNow():关闭线程池,线程的状态变为STOP。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的List。

线程池与其他的池化技术(数据库连接池,Http连接池)的思想差不多。好处也是显而易见的:1.降低资源消耗(提高线程的复用性)2.提高响应速度(每次连接直接就可以用了,无需重新建立与连接过程)3.提高线程的可管理性(线程是系统资源,不可能无限制创建。通过线程池可以统一的分配,调优和监控)。

Executor框架结构(三大部分)

1.任务(Runable/Callable):执行任务需要实现Runable或者Callable接口。Runable或者Callable都能被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。
2.任务的执行(Executor):任务执行机制的核心接口 Executor ,以及继承自 Executor 接口的 ExecutorService 接口。ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 这两个关键类实现了 ExecutorService 接口。
3.异步计算的结果(Future):Future 接口以及 Future 接口的实现类 FutureTask 类都可以代表异步计算的结果。
当我们把 Runnable接口 或 Callable 接口 的实现类提交给 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行。(调用 submit() 方法时会返回一个 FutureTask 对象)

Executor使用过程

1.主线程首先要创建实现Runnable或者Callable接口的任务对象。
2.把创建完成的对象直接要给ExecutorService执行(ExecutorService.execute(Runnable Command))可以使用execute方法也可以用submit方法(Callable要用submit)
3.如果使用submit提交任务,则会返回一个FutureTask对象(Runnable也会有)
4.最后利用FutureTask.get()方法来等待任务执行完成。主线程也可以使用FutureTask.cancel取消任务的执行。

ThreadPoolExecutor类分析

ThreadPoolExecutor 3 个最重要的参数
corePoolSize : 核心线程数线程数定义了最小可以同时运行的线程数量。
maximumPoolSize : 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
workQueue: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
ThreadPoolExecutor其他常见参数:
keepAliveTime:当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁;
unit : keepAliveTime 参数的时间单位。
threadFactory :executor 创建新线程的时候会用到。
handler :饱和策略(抛出异常、调用自己的线程运行任务、直接丢弃、丢弃最早的任务)。
创建线程可以利用ThreadPoolExecutor的构造函数(推荐),也可以利用Executors(FixedThreadPool、SingleThreadExecutor、CachedThreadPool)去创建。

常见的线程池:

FixedThreadPool:
可重用固定线程数的线程池,不推荐的原因:使用的是无界队列LinkedBlockingQueue(队列的容量为 Intger.MAX_VALUE),容易遭成oom。
SingleThreadExecutor:
单线程的线程池,也是使用的无界队列LinkedBlockingQueue。
CachedThreadPool:
根据需要创建新线程的线程池。
ScheduledThreadPoolExecutor:
主要用来在给定的延迟后运行任务,或者定期执行任务

线程池大小确定:
CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
I/O 密集型任务(2N): 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值