线程与进程:
线程是程序执行的一条路径, 一个进程中可以包含多条线程
一个进程实际上就是一个正在运行的程序, 线程实际上就是CPU的最小执行单位
并行与并发:
并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。
JVM是否是多线程:
JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。
继承Thread
* 好处是:可以直接使用Thread类中的方法,代码简单
* 弊端是:如果已经有了父类,就不能用这种方法
实现Runnable接口
* 好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的
* 弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂
线程休眠: Thread.sleep(long 毫秒)
线程守护: setDeamon(true). 当一个线程被设置成守护线程时, 那么当非守护线程执行完以后, 守护线程就自动结束了
线程加入(插队):
join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
join(int), 可以等待指定的毫秒之后继续
线程礼让:
yield让出cpu.
线程同步:
* 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
* 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
同步代码块
* 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
* 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
同步方法:
在方法的声明加上synchronized关键字
非静态的同步方法的锁对象是神马?
答:非静态的同步方法的锁对象是this
静态的同步方法的锁对象是什么?
是该类的字节码对象
同步代码块嵌套造成的死锁问题
* 第一条线程进入后拿到s1这把锁, 同时第二条线程进入后拿到s2这把锁
* 这时第一条线程需要拿到s2这把锁, 同时第二条又需要拿到s1这把锁
* 但是只有当同步代码块里的代码都执行完以后, 才会释放锁,也就是说此时其他线程才能拿到锁
* 这个时候出现的问题是: 第一条线程由于拿不到s2这把锁, 因此没有办法执行完同步代码块, 也就没法释放s1这把锁
* 同理, 第二条线程由于拿不到s1这把锁, 因此没有办法执行完同步代码块, 也就没有办法释放s2这把锁
饿汉式和懒汉式的区别(单例设计模式)
* 1,饿汉式是空间换时间,懒汉式是时间换空间
* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象, 为了解决这个问题, 需要在懒汉式中使用同步, 但是这样做就使效率变低了
线程间的通信
1,在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
2,为什么wait方法和notify方法定义在Object这类中?
1) 首先Object是所有类的父类
2) 锁对象是任意类型的
3) 我们希望任意一个对象都有wait和notify方法.
4) 因此我们需要将wait 和 notify方法定义在Object类中
3,sleep方法和wait方法的区别?
sleep方法在同步函数或同步代码块中,不释放锁,也就是说必须将同步代码块里的代码执行完毕后才会释放, 在此期间, 其他线程不能执行
wait方法在同步函数或者同步代码块中,如果调用了该方法, 锁就被释放了, 也就是其他的线程可以执行了
线程的五种状态:
新建状态: 创建线程对象
就绪状态: 有执行资格, 但是没有执行权, 也就是说抢到Cpu的执行权就可以执行
运行状态: 既有执行资格, 又有执行权
阻塞: 没有执行资格, 也没有执行权
死亡: run方法执行完毕
回到就绪状态
线程池的概念:
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,
尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池
多线程:
死锁, 线程间通信
设计模式:
装饰设计模式
单例设计模式
工厂方法模式
简单工厂模式 |
|