我是一个初学者,想学习一下多线程。满世界都是高并发多线程,我就没遇到一个讲的明白的。
个人觉得,绝大部分的技术发明出来,都是为了解决一个生活中的普遍问题而产生的。既然是普遍问题,他就不应该很难理解。如果问题讲的难了,要么是装逼,要么是不会!
一、线程和线程池概念:
重点:
1、Java的线程依赖内核线程,我们创建的线程不直接操作底层(cpu)。我们在代码中创建的每一个线程都会在操作系统中有一个内核线程与之对应(1:1),jvm通过操控内核线程间接操控底层。
所以说线程是一种稀缺资源,主要体现在与之对一个的内核线程的稀缺。
(可引申执行过程,结合现实笔记本8核,8线程并行阐述,组织语言以后再说吧)
2、由于以上,如果能够重用线程就很舒服。所以就出现了线程池,我们说的线程池是Java已经
二、什么时候选择线程池
刚有点理解,视频开始卖课,真头大。。。。
三、线程池相关代码学习:
ps:无意之中听到了尚学堂赵珊珊老师的课,虽然有一些细节我持保留意见。但是,他确实通俗易懂的,讲了线程池。我从一个菜鸟角度看,与其讲的晦涩难懂,带着错误的听明白一点呢。
https://www.bilibili.com/video/av26354412/?p=4
1.线程池代码
1)
新建一个线程类实现runnable接口,重写run方法很简单,打印当前线程的名字,以便我们知道线程的执行情况。
2)
测试,创建线程池,并指定参数。先忽略keepAliveTime和多余任务无法执行的问题。注意现在有8个任务需要执行。
测试结果:
结果分析:程序运行完了,八个任务执行完了,最多用到了3个线程(符合核心线程数)。
3)
线程类不变,修改main方法
测试结果:
结果分析:程序运行完了,8个任务执行完,用到了两个线程(符合核心线程数,并且还有点轮询的意思 ,开个玩笑。。。千万别当真)。
这差不多可以说明一点,核心线程有能力执行任务时,不会创建新的线程(当然总线程数目肯定不会超过最大线程数)执行任务。我这里说差不多,是因为我们没有考虑任务队列满的情况。在下一个循环到来之前,任务完全可以被执行完,线程可以在下个任务到来时直接执行下一个。
4)再次修改main方法,我们讲睡眠去掉,将循环次数扩大到100.
结果分析:程序没有执行完,8(最大线程数+队列长度)个任务被执行完毕,用到了3个线程执行任务。多次测试结果都是这样,只有8个任务被执行了,相当于3个任务被最大线程数执行,之后有5个在队列中的任务被执行。但是因为循环没有结束,还有任务想要交给线程池执行,却卡住了,没有被执行。这可能就是传说中的被拒绝吧。
5)
再次修改main,队列长度不做限制。
结果分析:程序运行完,100个任务都被执行了,2个线程执行了任务。这说明,当任务队列足够大,他会将执行不过来的任务放到队列中,使用核心线程慢慢执行。
6)
修改main,队列定长,测试任务执行不完的临界点。
总结:
多次测试发现**,当任务总数<核心线程+队列长度**,任务被正常执行完,并且只需要核心线程参与任务执行。最大线程数+队列长度>当任务总数>核心线程+队列长度,任务也会被执行完,但是会创建核心线程数之外的线程参与任务执行。当任务总数>最大线程数+队列长度,任务执行不完,只有最大线程数+队列长度个任务会被执行。
2.内置线程池
jdk1.5之后,Java提供了内置线程池。我理解就是看我们自己写得不好,人家给写了几个线程池,供我们直接用。而且,我们会发现,因为其没有限制队列大小,所以不会出现我们测试的那种执行不完任务的情况。
1)单线程
核心线程数=最大线程数=1
2)固定线程数
其参数制定了核心线程数和最大线程数。
3)缓存
没有核心线程数,但是规定了最大线程数是integer最大值,近乎于没有上限的情况了,会根据任务数量灵活创建线程执行。
4)定时
这个定时的也能执行,但是没太看明白这个意思。。。
其实,这样看也没有什么难理解的,主要是应用。很多教程没有让我觉得满意的原因也是因为这一点,理论讲的再好不会用,锤子用没有。
3.多线程的应用
暂时没有找到合适的代码论证。