(1)多线程概念
线程:进程当中的一个执行单元 负责进程当中程序运行 一个进程当中至少有一条线程
一个进程当中可以存在多条线程 这样的应用程序称之为多线程
进程:正在执行的程序 就是应用程序 在内存当中的那片空间
并发:如果一个进程当中有多条线程同时运行 专业术语称为:并发
多线程有点:多线程的并发执行可以合理的提高cpu的执行效率 如果线程比较多 性能也会降低
cpu:
(2):创建多线程的两种方式
1.继承Thread类
定义一个类 继承Thread类 自定义的类就具备多线程的特点
重写父类当中run()方法 将要同时执行的代码 定义在run() 方法当中 称之为线程任务
2.实现Runnable接口
定义一个类 实现Runnable接口
覆写Runnable接口当中run()方法 定义线程任务
创建一个Thread类 将Runnable接口的实现类作为参数传递
调用Thread类当中static方法 启动线程
(3)两种方式的区别
方式一:继承Thread类的方法:线程对象和线程任务结耦在一起 继承只能单继承
方式二:实现Runnable接口的方法:避免了单继承的局限 更加具备面向对象特点 更好的扩展性
(4)多线程的状态图
新建态 :线程对象刚刚创建 new Thread();
就绪态:进入一个容器当中进行等待,等待cpu的执行权。当调用static() 方法的时候,线程进入就绪态
运行态:在容器当中进行等待的线程获得了cpu的执行权,此时进入运行态 调用run() 方法
堵塞挂起态:线程执行的过程中 遇到了一些堵塞方法{sleep(),wait()},程序进入堵塞挂起态
终止态:线程最终运行完毕
(5)为什么不直接使用Thread类?
Runnable和Thread都可以实现run方法,但一个是接口,一个是类,前者可以无限地创建Thread进行run,而后者进行一次run之后就无法再次run。注意:Thread执行了start之后不可以再次执行start!
因此,要实现线程能重复运行,如果采用XXX extends Thread,那么每次运行都必须new一个XXX,这十分损耗资源;如果使用XXX implements Runnable,那每次运行只需要新开一个线程new Thread(xxx)即可,节省了很多时空消耗。
(6)多线程当中的异常信息
哪条线程发生异常 哪条线程终止 其它线程继续运行
(7)多线程解决数据安全问题
synchronized修饰 加同步
同步块解决
synchronized(对象){
//被同步的代码
}
同步函数解决
访问权限修饰符 synchronized 返回值 方法名(){
}
synchronized加同步解决 优点:解决了数据安全问题 缺点:降低了程序的运行效率
(6.1)出现数据安全问题的原因
1.有共享对象
2.对共享对象进行了相关的运算
(7.1)多线程同步有几种实现方法,都是什么?
同步的实现方面有两种,分别是 synchronized,wait 与 notify
请说出你所知道的线程同步的方法。
wait():使一个线程处于等待状态,并且释放所持有的对象的 lock。sleep():使一个正在运行的线程处
于睡眠状态,是一个静态方法,调用此方法要捕捉 InterruptedException 异常。notify():唤醒一个处
于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是
由 JVM 确定唤醒哪个线程,而且不是按优先级。Allnotity():唤醒所有处入等待状态的线程,注意并不
是给所有唤醒线程一个对象的锁,而是让它们竞争。
(8)同步函数和同步块区别
1.形式不同
2.锁对象不同
同步函数:锁对象只能时this锁
同步块:任意对象
3.范围不同
4.当线程当中需要使用多个同步时 使用同步块
当线程当中需要一个锁对象的时候 使用同步函数
(9)死锁
当线程当中出现了多个同步时 同步当中嵌套了其他同步 容易引发死锁
死锁案例
(10) 单例模式下多线程问题
饿汉模式不会出现并发访问 数据安全
懒汉模式:
(11)wait()和sleep()方法的区别
相同点:都能够让线程进入堵塞挂起状态
不同点:1.sleep(mills);必须指定时间
wait([mills]);可以指定 可以不指定 指定时间 使用方式和sleep相同
2.sleep指定的时间到了 线程会自动进入就绪状态
wait没有指定时间 需要被调用wait的对象去调用notify方法 进行唤醒
3.sleep定义在Thread类当中 只能时Thread类或者时子类对象才可以使用
wait定义在Object类当中 任何对象都可以调用
4.sleep不一定非要在同步当中使用
wait必须定义在同步当中
5.sleep执行到sleep,不会释放锁
wait执行到wait,锁释放
(12)为什么wait和notify方法定义在Object类当中
因为这两个方法在使用的时候 必须要有自己的锁 而这个锁对象this可以是任意对象 任意对象都可以调用的方法必须定义在Object当中