多线程

16、知识点总结


图片.png

1、线程和进程

进程:进程是指正在运行的程序。
线程:线程是进程中的执行单元,一个进程至少有一个线程。
多线程:一个程序中有多个线程在同时执行。
单线程程序:若有多个任务只能依次执行
多线程程序:若有多个任务可以同时执行

2、程序运行原理

分时调度

所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

抢占式调度

优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

3、多线程

多线程:一个程序中有多个线程在同时执行。

多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

4、主线程

jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。
那么,能否实现一个主线程负责执行其中一个循环,再由另一个线程负责其他代码的执行,最终实现多部分代码同时执行的效果?
能够实现同时执行,通过Java中的多线程技术来解决该问题。

5、创建线程方式

1、继承Thread类,重写 Thread 类的 run 方法。然后就是分配并启动该子类的实例
2、实现Runnable 接口,该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。


实现Runnable 接口.png

图片.png
继承Thread类和实现Runnable接口有啥区别呢?

(1)实现Runnable接口避免了单继承的局限性,所以较为常用。
(2)实现Runnable接口的方式,更加的符合面向对象思想,其实线程分为两部分,一部分线程对象,一部分线程任务。
继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,又有线程任务。
实现runnable接口,将线程任务单独分离出来封装成对象,在创建thread时作为一个参数传递并启动。Runnable接口对线程对象和线程任务进行解耦。

(将这个子类对象作为参数传递给Thread的构造函数,)类型就是Runnable接口类型。

6、线程对象调用 run方法和调用start方法区别?

线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。

7、多线程的内存图解

多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。


图片.png

当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。

8、获取线程名称

Thread.currentThread()获取当前线程对象
Thread.currentThread().getName();获取当前线程对象的名称
修改线程名字:用thread对象调用setName()写在开启线程之前

9、线程的基本状态以及状态之间的关系?

图片.png

【new:新建状态;等待状态;runnable:就绪状态;running:运行状态;blocked:阻塞状态;dead:死亡状态】

1.新建

【新建一个线程对象,分配内存】
用new语句创建的线程对象处于新建状态,此时它和其他java对象一样,仅被分配了内存。

2.等待

创建线程对象开始到调用start方法前,线程处于等待状态。

3.就绪

线程调用它的start()方法,进入就绪状态。处于这个状态的线程位于Java虚拟机的可运行池中,等待cpu的使用权。

线程进入就绪状态的情况

线程调用start()方法
正在运行的线程执行yield()方法
处于阻塞状态的线程:休眠状态的线程sleep状态超时

4.运行状态

处于这个状态的线程占用CPU,执行程序代码。在并发运行环境中,如果计算机只有一个CPU,那么任何时刻只会有一个线程处于这个状态。

线程进入运行状态的情况

只有处于就绪状态的线程才有机会转到运行状态。

5.阻塞状态

阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才会有机会获得运行状态。

阻塞状态分为三种:

(1)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

(2)同步阻塞:运行的线程在获取对象同步锁时,若该同步锁被别的线程占用,则JVM会把线程放入锁池中。

(3)其他阻塞:运行的线程执行Sleep()方法,或者发出I/O请求时,JVM会把线程设为阻塞状态。当Sleep()状态超时、或者I/O处理完毕时,线程重新转入就绪状态。

6.死亡状态

当线程执行完run()方法中的代码,或者遇到了未捕获的异常,就会退出run()方法,此时就进入死亡状态,该线程结束生命周期。

9、线程的sleep()方法和yield()方法有什么区别?

sleep()方法和yield()方法都是Thread类的静态方法,都会使当前处于运行状态的线程放弃CPU,把运行机会让给别的线程。两者的区别在于:
(1)sleep()方法在放弃CPU,把运行机会让给其他线程时,不考虑其他线程的优先级,因此会给较低优先级线程一个运行的机会;yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。
(2)当线程执行了sleep(long millis)方法,将转到阻塞状态,参数millis指定睡眠时间;当线程执行了yield()方法,将转到就绪状态。
(3)sleep()方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何异常。
(4)sleep()方法比yield()方法具有更好的可移植性。

10、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,他们有什么区别?

(1)sleep 是线程类(Thread)的方法,wait 是Object 类的方法。
(2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
(3)wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)
(4)sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。

12、多线程线程同步

多线程同时操作一个共享数据,往往出现安全问题。

解决安全性问题的根本办法:当一个线程进入数据操作的时候,无论是否休眠,其他线程只能等待。保证了数据操作只能有一个线程来完成

其实,线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

解决安全问题,Java提供了同步技术

线程同步的方式有两种:

方式1:同步代码块

同步代码块: 在代码块声明上 加上synchronized
synchronized (锁对象) {
可能会产生线程安全问题的代码
}
同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。


同步代码块执行原理

加了同步之后,线程进同步需要判断锁,获取锁,出同步需要释放锁,导致程序运行速度的下降

方式2:同步方法

好处:代码简洁

将共享数据和同步抽取到一个方法中
13、Lock接口

因为使用同步代码块或者同步方法时,线程在同步中时锁被获取我们不知道在哪释放,如果此时线程出现异常,锁对象将无法被释放。
所以在jdk1.5中有一个新特性就是Lock接口。

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。

Lock接口中的常用方法


图片.png

图片.png

使用Lock接口的实现类ReentrantLock()获取lock锁对象。


图片.png

图片.png

使用Lock接口实现同步步骤:
1、使用Lock接口的实现类ReentrantLock()获取lock锁对象
Lock ck = new ReentrantLock();
2、在可能会产生线程安全的代码前后分别加上ck.lock();和ck.unlock()

14、死锁

同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。

多线程出现同步嵌套


图片.png

多个同步,同步中有嵌套。锁对象具有唯一性。
当一个线程进入一个同步中时,再次进入里边的同步时的锁被其他线程所拿走,而刚好这个拿走锁的线程进入里边同步的锁被刚才那个线程拿着,两边都无法进入嵌套的同步中也就无法释放锁,所以才出现了死锁。

15、等待唤醒机制

通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。

等待唤醒机制所涉及到的方法:
wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

图片.png

3)为什么wait(),notify()方法要和synchronized一起使用?

因为wait()方法是通知当前线程等待并释放对象锁,notify()方法是通知等待此对象锁的线程重新获得对象锁,然而,如果没有获得对象锁,wait方法和notify方法都是没有意义的,即必须先获得对象锁,才能对对象锁进行操作,于是,才必须把notify和wait方法写到synchronized方法或是synchronized代码块中了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容