Java线程生产者消费者模式与线程池
首先先简单地介绍一下生产者消费者模式:
例如学到的知识
Teacher(上课讲知识,造知识)=========(知识)>>Student(学生学习知识,用知识)
这就是简单的生产者消费者模式
下面来介绍一个示例来学习此概念
有一个类似Hibernate的SessionFactory工厂
MakeSessionFactory为造工厂,GetSessionFactory为使用工厂,则SessionFactory为中间类
现在实现初步的生产者消费者:version 1 code:
thread_1.SessionFactory
thread_1.GetSessionFactory
thread_1.SetSessionFactory
thread_1.SessionFactoryTest
有如下问题:
A:在每个线程中都创建了资源,每次的输出结果是null-0
已解决:在生产者消费者类中提供一个带SessionFactory的构造函数,每次传递的时候都能保持使用SessionFactory同一个对象
B:为了数据能够出现效果,加入了大条件循环,但是给出了不同的值:
同一个数据出现多次:因为cpu
配置文件名和工厂名不匹配:那是因为如果if语句刚执行好没结束就没else抢去了执行权,所以在输出时的信息不准确,例如:
in get... sessionFactory is[SessionFactory{factoryName='spring-log4j.appender.stdout.layout.ConversionPattern', configName='applicationContext.xml'}]==========
而且执行时顺序也发生了问题,如下
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097274]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097273]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097272]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097271]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097270]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097269]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097268]==========
10:15:01,828 INFO Spring4Hibernate5BaseUtils:182 - in make i = [-2146097267]==========
10:15:01,827 INFO Spring4Hibernate5BaseUtils:182 - in get... sessionFactory is[SessionFactory{factoryName='interface org.hibernate.SessionFactory', configName='hibernate.cfg.xml'}]==========
关于输出内容写到了日志,可以复制log4j.properties文件来实现,可以到日志中去查看可以发现有以上这种情况
C:现在来解决以上问题:解决方案是加锁,加锁需注意:
1.不同种类的线程都要加锁
2.不同种类的线程加的锁必须是同一把
如果不是同一把锁会发生空的情况,这也会作为一个例子
D:加好同一把锁后发现输出一大片不太好看,可以通过java等待唤醒机制来实现
Object类中提供了三个方法:
wait():等待
notify():唤醒单个线程
notifyAll():唤醒全部线程
这些方法定义在Object类中的原因是通过锁对象调用,而获取的锁可以是任意对象,所以这些方法必须定义在Object类中才能被任意类型的子类调用
finalVersion:把设置和获取的操作封装成了功能,并增加了同步,
设置只需要调用实体类方法即可
线程池:
好处:
线程池里的每一个线程结束后并不会死亡,而是回到线程池中成为空闲状态,等待下一个对象来调用
A:创建一个线程池对象,控制要创建几个线程对象。
public static ExecutorService newFixedThreadPool(int nThreads)
B:这种线程池的线程可以执行:
可以执行Runnable对象或者Callable对象代表的线程
做一个类实现Runnable接口。
C:调用如下方法即可
Future> submit(Runnable task)
Future submit(Callable task)
D:我就要结束,可以吗?
可以。
Callable:带返回值的Runnable式接口,接下来做一个示例来描述我的Callable