线程与进程之间的联系与区别:
进程包含一个至多个线程(java进程至少包含两个线程,main和GC)
进程是分配内存空间的单位
线程是执行和调度的单位
多线程的创建
1.继承Tread类,重写run方法,在方法中编写线程需要执行的语句,在main方法中start
2.实现Runnable接口,实现run方法(常用)
3.实现Callable接口,实现call方法
线程的生命周期
当一个线程创建并启动时,并不是直接进入运行状态,而是进入等待状态,等待cpu调度,分配内存进入运行,当一些情况发送会进入阻塞状态或者正常结束
当发生这些情况会是线程进入阻塞状态
1.当调用sleep方法,主动放弃资源
2.当遇到同步锁被占用
3.一个线程在等待其他线程notify
4.线程调用了一个阻塞式IO方法,该方法返回前,一直处于阻塞状态(例如,TCP中服务端在等待接收
(serverSocket.accept())
)
当线程在阻塞状态结束后,进入等待状态,等待cpu的调度
以下是结束阻塞后,进入运行状态
1.同步锁中的sleep(),他是占着资源进行休眠,所以其他线程不可以抢占,等时间一过去就会进入运行
2.线程调用了阻塞式IO方法返回,就进入运行状态
3.其他线程释放同步锁,线程抢占到,从阻塞进入运行状态
4.线程接收到notify
线程消亡
1.正常执行完run()方法
2.线程抛出一个未捕获的异常
3.使用stop强行让线程终止(容易出现死锁)
线程同步
为了避免多个线程访问同一个资源,造成不安全的现象,引入同步锁,这个锁可以是不变的对象、类,资源,这个锁只能被一个对象占用,一旦占用,其他访问的线程进入阻塞状态,只有当结束,释放锁,其他线程才有资格去访问。
同步代码块
synchronized(锁){
//锁住需要的,降低同步带来的减速
}
同步方法
public synchronized void a{
//同步方法的执行速度相对来说更低,出现异常需要捕获,不能抛出
//静态方法不能有同步方法
}
死锁
线程A在等待线程B所占用的资源,线程B等待线程A锁占用的资源