JavaSE-day19

生产者与消费者模式

原因
	生活中工厂会出现两种情况:
		情况1:生产的商品过多,导致库房无法存储,此时应该停止生产,等待消费
		情况2:消费太快,导致库房没有商品,此时应该停止消费,等待生产
		注意:消费即销售出去的商品
分析
	工厂(对象)
		属性
			1、最大存储商品的数量
			2、当前存储商品的数量
		方法
			生产商品的方法(同步方法)
				判断当前存储商品的数量是否小于最大存储商品的数量
				小于
				当前存储商品数量++
				并且提示xxx生产了一个商品,当前存储的商品数量为xxx
				唤醒消费者线程
				大于等于
				提示当前库房已满,请停止生产
				让生产者线程休眠
			消费商品的方法(同步方法)
				判断当前存储的商品数量是否大于0
				大于
				当前存储的商品数量--
				并且提示xxx消费了一个商品,当前存储的商品数量为xxx
				唤醒生产者线程
				小于等于
				提示库房已空,xxx请停止销售
				让消费者线程休眠
				
	生产者(对象)
		属性
			工厂
		构造函数
			传入工厂对象
		方法
			无限调用工厂中的生产方法
	消费者(对象)
		属性
				工厂
			构造函数
				传入工厂对象
			方法
				无限调用工厂中提供商品的方法

线程优化(重点)

优化的原因

一个线程在存活时大约占据1mb运行内存
线程在使用完毕后需要等待GC回收
此时因为大量线程在等待GC回收而占据着内存
导致程序运行效率低下

解决思路

1、控制创建线程的数量
2、利用已经空闲的线程,去执行新的任务(线程的复用)
3、当线程处于空闲状态时,能被回收就回收
jdk提供了这个思路的工具,这个工具叫线程池(Executor)

线程池(Executor)

概念:一个用于管理线程的容器,包含线程的创建,复用及回收
优点
	1、使用线程池可以不用考虑线程的创建,复用及回收,方便使用
	2、节省运行内存,提高代码的执行效率
	3、无需频繁的创建与销毁线程

体系

Executor(接口)

子接口:
	ExecutorService(接口)
		方法:
			shutdown();关闭线程池
			submit();提交线程任务给线程池
	ScheduleExecutorService(接口): 调度线程池
子类:
	ThreadPoolExecutor

线程池获取的工具类(Executors)

可以让你简单的获取到线程池对象

获取线程池

固定线程池(newFixedThreadPool)

作用:获取一个线程数量恒定的线程池
方法:
	Executor.newFixedThreadpool(线程数量);

可变线程池(newCachedThreadPool)

	作用:获取线程数量不固定的线程池
	方法:
		Executors.newCachedThreadPool();

单例线程池(newSingleThreadExecutor)

作用:获取一个线程数量为一的线程池
方法:
	Executors.newSingleThreadPool();

调度线程池(newScheduledThreadpool)

作用:获取一个调度线程池
方法:
	Executors.newScheduledThreadPool(int corePoolSize);

单例调度线程池

作用:获取只有一个线程的调度线程池
方法:
	Executors.newSingleThreadScheduledExecutor();

抢占线程池(了解)

作用:获取一个抢占线程池
方法:
	Executor.newWorkStealingpool();
特点:
	1,jdk1.8出现
	2,该线程池中有一个算法,叫做窃取算法.该算法的优点将任务平分下去,当该线程中一个线程执行完自己的任务后,会帮助还没有完成任务的线程.为了提高线程任务的执行效率
	3,该线程池的线程都是守护线程,所以当进程中所有前台都被销毁后,该线程池中的所有线程都会被销毁,该线程池也会被销毁
	4,该线程池如果被关闭,也需等待其中任务执行完毕后才会关闭线程池.前提时在该线程执行线程任务时,有别的前台线程存活

调度线程池特点及特有方法

调度线程池:ScheduledExecutorService
特点:
	1、属于ExecutorService的子接口
	2、特有方法:调度
特有方法:
	schedule:延迟多长时间后开始执行任务
	scheduleAtFixedRate:延迟多少时间后开始执行任务,间隔多少时间后重复执行
			间隔时间:
					前一次任务开始时间至本次任务开始时间
			注意:如果代码执行时间超过间隔时间,那么下次任务执行将会在上一次任务执行完毕后,直接执行
	scheduleWithFixedDelay:延迟多少时间后开始执行任务,间隔多少时间后重复执行
			间隔时间:
					间隔时间:前一次任务结束时间至本次任务开始时间

ThreadPoolExecutor

概念:固定线程池,可变线程池,单例线程池获取到的线程池对象,本质就是该类的对象

因为在阿里白皮书中说过,为了深入理解线程池,建议所有开发人员使用ThreadPoolExecutor创建线程池对象
构造函数:
		ThreadPoolExecutor pool = 
				new ThreadPoolExecutor(int corePoolSize,
									   int maximumPoolSize,
									   long keepAliveTime,
									   TimeUnit unit,
									   BlockingQueue<Runnable> workQueue,
									   ThreadFactory threadFactory,
									   RejectedExecutionHandler handler)
		1参corePoolSize:核心线程数量,线程池中最小线程数量
		2参maximumPoolSize:线程池中最大线程数量
		3参keepAliveTime:当非核心线程闲置多长时间后会被系统回收
		4参unit:时间单位
		5参workQueue:存储线程池执行的任务的集合
		6参threadFactory:线程工厂,在线程池中创建线程
		7参handler:当线程池中线程任务多余线程时的策略

线程任务优化

因为Runnable在执行完任务后,无法返回数据,所以对其进行优化

Callable(接口)

Callable与Thread结合使用

步骤:
	1、创建Callable接口的子类对象
	2、创建FutureTask对象,并传入Callable的子类对象
		注意:因为FutureTask是Runnable的子类(子转父)
	3、创建线程对象,并传入FutureTask的对象
	4、启动线程
	5、,使用FutureTask对象调用get方法,获取Callable中call方法的返回值(对象名.get())
注意:
	注意:
		get方法会阻塞程序运行,直到阻塞到call方法执行完毕,拿到返回值才可以

Callable与现场池结合使用

步骤:
	1、创建线程池对象
	2、提交线程池给对象,并获取其返回值
	3、关闭线程池
	4、使用步骤二的返回值调用get方法,获取call方法的返回值
注意:
	如果步骤二传入的线程任务是Runnable对象,那么就没有步骤四
	如果步骤二传入的线程任务是Callable对象,那么就可以选择使用步骤四

锁的优化

原因:因为在使用synchronize时发现不是很方便,所以对其优化

Lock

体系
	Lock(接口)
		方法:
			lock:关闭锁
			unlock:释放锁
		子类
			ReentrantLock: 重入锁
			ReentrantReadWriteLock:
				方法:
					readLock:提供一个Lock对象(读的锁对象)
					writeLock:提供一个Lock对象(写的锁对象)
					注意:读的锁对象与读的锁对象互不干扰
							   写的锁对象与写的锁对象互斥
							   读的锁对象与写的锁对象互斥

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值