多线程
1.1 进程与线程的概念
进程:是操作系统分配资源基本单位;
线程:线程是微进程,进程中会包含若干线程,进程是以线程作为基本单位进行调度的;进程中的线程之间是资源共享的;
进程和线程的状态转变图【五态图或者七态图】 ★★
参考:https://www.processon.com/view/link/60481e9b7d9c082c92e63743
进程是动态概念;程序是静态概念;
程序+数据+cpu动态执行=进程
1.2 多线程编程
多线程的创建方式:
创建新执行线程有两种方法。
一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。
另外一种:通过继承实现Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
将实现Runnable接口的实例对象作为Thread类的构造参数创建线程
补充:Callable接口的补充使用;使用Runnable接口实现的多线程可以避免单继承局限,但是Runnable接口实现的多线程会存在有一个问题:
Runnable接口里面的run()方法不能返回操作结果。所以为了解决这样的问题,
从JDK 1.5开始对于多线程的实现提供了一个新的接口:java.util.concurrent.Callable
线程常用的方法;
线程只有执行了 start 方法之后,才会进入线程运行状态;如果只调用 run 方法则只是一个普通的方法调用;
常用的方法:start【进入就绪态】、run【核心处理方法、业务逻辑处理】、join【进入阻塞态】、sleep【进入阻塞态】、yield【进入就绪态】
1.3 线程同步
线程在执行过程中,需要保证多个线程之间的有序执行;这是需要进行线程同步处理;
synchronized关键字、wait-notify加锁同步机制;
synchronized关键字的使用:
synchronized关键字可以修饰:方法、语句块;
表示方法、语句块是在进行线程同步处理;
synchronized枷锁对象只能是对象类型,不能使基本类型;如果是基本类型,则需要使用包装类类型;
wait-notify机制一定要在synchronized加锁的情况下进行使用;
扩充:
线程死锁【进程死锁】:
线程【进程】死锁:当多个进程在申请有限的关键资源时,各自持有部分关键资源,并且相互等待对方持有的支援才能继续运行;
这样就进入了相互等待状态;死锁的状态;
死锁产生的四个条件:
互斥条件;【资源具有互斥性,只能有一个进程使用】
不可剥夺条件;【一旦持有之后,不会主动放弃】
请求与保持条件;【先申请一部分资源,再继续申请后续资源】
循环等待条件;【资源不足时可以继续等待】
以上这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
破坏上述资格条件之一都可以解决死锁的问题;
线程同步示例:
使用生产者和消费者的例子说明一下如何使用synchronized关键字以及wait-notify机制进行线程同步;
场景:有一个仓库,存储量是n,采用先进后出的栈的方式进行货物存取;有生产者生产商品之后,会放入仓库中;
有消费者会从仓库中取出一个货物进行消费;请使用线程同步的方式达到生产者和消费者可以无冲突的使用仓库进行生产消费;
分析:关键资源:仓库;生产者和消费者都会抢占这个仓库的核心资源;