多线程机制 (三)

对线程的一些知识拓展。

线程池原理

参考文章来源:https://blog.csdn.net/pangpang123654/article/details/75949823
应该是最全面的吧,没有看完,确实很多。

线程池是一种多线程处理形式,处理过程中将任务添加到队列, 然后在创建线程后自动启动这些任务,线程池的基本思想是开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。 当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源

面向对象编程中,对象创建和销毁是很费时间的,因为创建一个对象要获取内存资源或者其他更多资源。 在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。 所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是对一些很耗资源的对象创建和销毁,如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些“池化资源” 技术产生的原因。

这让我想到一个印象深刻的例子,比如说某 兼职平台 每次找兼职做任务,寻找到做兼职的人需要花费时间和成本,当派他们出去发传单、宣传的时候还要掌握他们的动态,结束时再一一安排好,很麻烦, 但是如果留下这些人的微信,建立了微信群,以后做兼职就从这里面招人, 没有了寻找的成本, 也不用每次之后结工资,可以建立一份合同,可以月结之类的,看起来还是兼职,其实拥有了长期工作的高效率和低成本。

(仅供理解,不要映射线程池的其他功能,如果觉得会误导,不看例子也可以,类比有时候能够有助理解,但是有时候会让我们陷入类比的逻辑中,找不到原本想要表达的本质,我常常就在看完别人的类比故事之后脑子里能想到的只有故事,而没有想要表达的逻辑概念,所以有时候觉得类比当然要越生动活泼越好,其实有时候南辕北辙,让别人只记住了例子,没法和原本的概念联系起来)

这就线程池的好处, 因为它已经有了一批对象是创建好的,所以没有了创建对象的成本,而且对象不需要再销毁,即它们已经由一次性作用变为长期性作用。

线程池主要有如下几个应用范围:

  1. 需要大量的线程来完成任务,且完成任务的时间比较短,比如 Web 服务器完成网页请求这样的任务, 因为单个任务小,而任务数量巨大,比如一个热门网站的点击次数。 但相对于长时间的任务,比如一个 FTP 连接请求, 线程池的优点就不明显了,因为 FTP 会话时间相对于线程的创建时间长多了。
  2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3. 接受突发性的大量请求, 但不至于使服务器因此产生大量线程的应用。 突发性大量客户请求, 在没有线程池情况下,将产生大量线程, 虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限。

线程池的简单实现

一般一个简单线程池至少包括下列组成部分。

  1. 线程管理器(ThreadPoolManager):用于创建并管理线程池。
  2. 工作线程(WorkThread):线程池中线程
  3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
  4. 任务队列:用于存放没有处理的任务,提供一种缓冲机制。

Java提供的四种类型线程池

1. newCachedThreadPool ——可变尺寸的线程池(缓存线程池):
(1)工作线程的创建数量几乎没有限制, 这样可以灵活地往线程池中添加线程。
(2)如果长时间没有往线程池中提交任务, 即如果工作线程空闲了指定时间(默认为一分钟), 则该工作线程将自动截止, 终止后,如果你又提交了新的任务, 则线程池重新创建了一个工作线程。

2. newFixedhreadPool ——固定大小的线程池:
创建了一个指定工作线程数量的线程池(线程数量固定)。 每当提交了一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中(等待有工作线程结束上一个任务之后实现这个任务)。

3. ScheduledThreadPool ——调度线程池:
创建一个定长的线程池, 而且支持定时的以及周期性的任务执行。

4. SingleThreadExecutor——单例线程池:
创建一个单线程化的线程池, 即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行。 单工作线程最大的特点是可保证顺序地执行各个任务, 并且在任意给定的时间不会有多个线程是活动的。

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

public class exp9_1 {
	public static void main(String[] args) {
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();	
		for (int i = 0; i< 10 ;i ++) {
			final int index = i;
			try { Thread.sleep(1000);}
			catch(InterruptedException e) { e.printStackTrace();}
			cachedThreadPool.execute(new Runnable() { public void run() 
				{System.out.print(index + " ");}});
		}
	}
}

输出结果:

0 1 2 3 4 5 6 7 8 9 

本例通过 Executors 类的 newCachedThreadPool() 方法创建了一个 ExecutorService 类型的可缓存线程对象 cachedThreadPool 。当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60 s 无执行的)线程,当有任务来时,又智能地添加新线程来执行。(就像是电脑上暂时不用的应用我们会先关掉,用的时候再打开,有提高性能、减少占用的意识)

Executors 类是线程池工具,具有多个创建线程池的静态方法,通过调用 execute(Runnable command)方法执行线程对象(匿名类创建的)任务。
本例使用了 ExecutorService 接口, 它提供了管理终止线程的方法,一个 submit 方法,用来创建 Future对象(跟踪一个或多个异步任务执行状况。)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值