多线程
2023-04-20 19:53:13 10 举报
AI智能生成
多线程的基础学习理解及应用
作者其他创作
大纲/内容
四、线程的生命周期【重点】
线程的状态【阻塞】
线程的5种状态:创建状态---->就绪状态---->运行状态---->阻塞\等待状态---->终止状态
五、线程死锁【理解】
当第一个线程拥有A对象的锁标记,并等待B对象的所标记。同时第二个线程拥有B对象锁标记,同时等待A对象的锁标记时,产生死锁
六、线程通信【理解】
若干个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个能存储多个产品的缓冲区,生产者将生产的产品放入缓冲区中,消费者从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个满的缓冲区中放入产品。
wait():当前线程释放锁对象, 并处于阻塞状态,进入等待队列,直到有别人唤醒
notify()、notifyAll() :随机唤醒一个正在等待的线程,唤醒所有等待队列中的线程
注意:所有的等待、通知方法必须在对加锁的同步代码块中
八、Lock锁
1、ReentrantLock:
Lock接口的实现类,与synchronized一样具有互斥锁功能
2、读写锁:ReentrantReadWriteLock
一种支持一写多读的同步锁,读写分离,可分别分配读锁,写锁。
支持多次分配读锁,使多个读操作可以并发执行
互斥规则:
写-写:互斥,阻塞
读-写:互斥,读阻塞写、写阻塞读
读-读:不互斥、不阻塞
在读操作远远高于写操作的环境中,可在保障线程安全的情况下,提高运行效率
一、进程和线程
进程:
运行中的程序称之为进程
特点:在单核cpu下,通过一个时间点上只有一个程序在运行,交替运行。宏观并行、微观串行
线程:
进程的组成部分,线程用进程中,单一的执行的顺序控制流程。同时也是cpu的调度单位
进程是可以有多个线程的,他们之间独立运行。交替执行。称之为多线程
区别:
进程是系统分配资源的单位,线程是cpu的调度单位
一个程序,至少包含一个进程
一个进程至少包含一个线程。线程是不能独立运行的,必须依附在进程中
进程之间是不能共享数据段地址,但是同一个进程下的线程是可以共享的
线程的组成部分:
cpu时间片:操作系统会为每个线程分配时间
运行数据:
堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象
栈空间:存储线程需使用的局部变量。每个线程都拥有自己的栈空间,线程的逻辑代码
二、创建线程【重点】
1、方式1:通过继承Thread类
2、方式2:通过实现Runnable接口
3、两种方式的区别:
1、java只支持单继承,所以继承Thread类就没办法继承其他的类,没有使用Runnable接口灵活
2、继承自Thread类,表示这个类就是一个线程类,可以直接启动线程实现Runnable接口,表示这个类是一个线程任务,需要创建线程对象从而执行这个线程任务
4、启动线程需要注意的问题:
1、不要调用run方法
2、一个线程只能调用一次start方法
5、线程的状态[基本]
New:初始状态
线程对象被创建,即为初始状态,只在堆中开辟内存,与常规对象无异
Ready:就绪状态
调用start()之后,进入就绪状态,等待OS选中,并分配时间片。
Running:运行状态
获得时间片之后,进入运行状态,如果时间片到期,则回到就绪状态。
Terminated:终止状态
主线程main()或独立线程run()结束,进入终止状态,并释放所持有的时间片
6、线程常见的方法:
1、设置线程名称 (setName、getName、Thread.currentThread获取当前线程对象),如果没有设置线程名称,那么默认的名称为Thread-0 Thread-N
2、设置线程的优先级 (setPriority、getPriority),如果没有设置线程的优先级,那么默认的优先级为5,线程有的优先级为1~10之间,设置优先级只是提高了抢占CPU的概率
3、线程休眠 (Thread.sleep(毫秒数)),让当前线程进入到休眠状态,并让出CPU使用权,直到休眠结束,才会继续抢占CPU
4、线程礼让(Thread.yeild()),让出CPU使用权,但是立马又会去重新抢占CPU
5、线程加入(join()),在当前线程中加入另一线程,必须要将另一个线程执行完之后才会继续执行当前线程
7、线程的状态(等待)
初始状态 ------ 就绪状态 ------- 运行状态 ----- 限期等待 -----无限期等待 -------- 终止状态
三、线程安全【重点】
1、线程安全问题
当多线程并发访问临界,如果破坏原子操作,可能会造成数据不一致
临界资源:共享资源(同一个对象),一次只可以有一个线程操作,才可以保证准确性
原子操作:不可拆分的步骤,被视作一个整体。其步骤不能打乱和缺省
2、线程同步
1、同步代码块
- synchronized(临界资源对象){ //互斥锁标记
- //原子代码
- }
- //原子代码
- }
2、同步方法
- public synchronized void sale(){ //互斥锁标记是this对象
- //原子代码
- }
- //原子代码
- }
3、线程同步买票案例
七、线程池
1、线程池概念:
如果有非常的多的任务需要多线程来完成,且每个线程执行时间不会太长,这样频繁的创建和销毁线程。
频繁创建和销毁线程会比较耗性能。有了线程池就不要创建更多的线程来完成任务,因为线程可以重用
线程池用维护者一个队列,队列中保存着处于等待(空闲)状态的线程。不用每次都创建新的线程。
2、线程池实现原理:
将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程
3、线程池中常见的类:
常用的线程池接口和类(所在包java.util.concurrent)
Executor:线程池的顶级接口。
ExecutorService:线程池接口,可通过submit(Runnable task) 提交任务代码。
Executors工厂类:通过此类可以获得一个线程池。
方法名:
newFixedThreadPool(int nThreads):获取固定数量的线程池。参数:指定线程池中线程的数量
newCachedThreadPool():获得动态数量的线程池,如不够则创建新的,无上限。
4、Callable接口
JDK5加入,与Runnable接口类似,实现之后代表一个线程任务。
Callable具有泛型返回值、可以声明异常。
语法:public interface Callable< V >{
public V call() throws Exception;
}
public V call() throws Exception;
}
JDK5加入,与synchronized比较,显式定义,结构更灵活
提供更多实用性方法,功能更强大、性能更优越
0 条评论
下一页