多线程相关
实现多线程的时候:
- 1,需要继承Thread类
- 2,必须要重写run()方法
- 3,线程在启动的时候,不要直接调用run方法,而是通过start()来启动
- 4,每次运行相同的代码,结果可能不一样,原因在于多线程中谁先抢占资源无法人为控制。
第二种实现方式:(使用了代理设计模式)
- 1,实现Runnable接口
- 2,重写run方法
- 3,创建Thread对象,将刚刚创建好的runnable的子类作为thread的构造参数
- 4,通过thread.start()来启动
推荐使用第二种方式:
- 1,java是单继承,可以将继承关系留给最需要的类。
- 2,使用runnable接口之后不需要给共享变量添加static关键字,每次创建一个对象,作为共享对象即可
线程的生命周期:
-
1,新生状态
当创建好当前线程对象之后,没有启动之前(调用start方法之前) -
2,就绪状态
准备开始执行,并没有执行,表示调用start方法之后。即当对应的线程创建完成,并调用start方法之后,所有的线程会添加到一个就绪队列中,所有的线程同时去抢占cpu资源。 -
3,运行状态
当当前进程获取到cpu资源后,就绪队列中的所有线程都会去抢占cpu资源,谁先抢到谁就运行,在执行的过程中就叫做运行状态(抢占到cpu资源,运行代码,执行逻辑) -
4,死亡状态
当运行中的线程正常执行完所有的代码逻辑或者是因为异常情况导致程序结束叫做死亡状态。
进入方式:- 正常执行到结束
- 人为中断,比如使用stop方法
- 程序跑出未捕获的异常
-
5,阻塞状态
在程序运行过程中,发生某些异常情况,导致当前线程无法再顺利执行下去,此时会进入阻塞状态,进入阻塞状态的原因消除之后,所有阻塞队列会再次进入到就绪状态中,随机抢占cpu资源,等待执行。
进入方式:- sleep
- 等待io资源
- join方法
**注意:**在多线程的时候,可以实现唤醒和等待的过程,但是唤醒和等待的对象不是Thread对象,而是我们设置的共享对象或者共享变量(Object类中有wait和notify方法)
多线程并发访问的时候回出现数据安全问题:
解决方式:
1、同步代码块
synchronized(共享资源、共享对象,需要是object的子类){具体执行的代码块}
2、同步方法
将核心的代码逻辑定义成一个方法,使用synchronized关键字进行修饰,此时不需要指定共享对象
线程操作的相关方法