线程状态
NEW 新建 RUNNABLE可运行状态 BLOCKED阻塞状态
WAITING 无限等待状态 TIMED_WAITING 计时等待
关于线程并发并行
在这里 并的对象是指CPU
并发是指 有个一CPU要去同时执行多个指令 交替执行
并行是指 有多个CPU要去执行多个指令 同时执行
进程和线程
进程:是正在运行的程序
线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:一个进程如果有多条执行路径,则称为多线程程序
实现多线程的方式有三种
首先 我们目的是去重写线程中的run方法,但是调用线程的时候的执行start方法
这是因为直接调用run方法实际上他就是一个普通方法没区别还是单线程调用
但是start是由jvm虚拟机去调用其中的run方法,这就是不同的线程
第一种 继承Thread类
步骤
定义一个类MyThread继承Thread类
在MyThread类中重写run()方法
创建MyThread类的对象
启动线程
第二种 实现Runnable接口
步骤
定义一个类MyRunnable实现Runnable接口
在MyRunnable类中重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程
第三种 实现Callable接口
步骤
定义一个类MyCallable实现Callable接口
在MyCallable类中重写call()方法
创建MyCallable类的对象
创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
创建Thread类的对象,把FutureTask对象作为构造方法的参数
启动线程
再调用get方法,就可以获取线程结束之后的结果。
那么如何挑选这三种呢
如果要是先继承别的类 我们就只能从第二第三中选.
如果要在run方法中要返回数据,我们就选择第三种,不用处理数据就第二种
设置和获取线程名称
currentThread() 返回对当前正在执行的线程对象的引用
通过getname setname去设置名字
但是!这里需要注意的是要用Thread对象去获取这些信息
线程休眠 作用 可以让不同的线程更有机会去抢夺资源
通过Thread去调用sleep方法 传入毫秒值 进行休眠
线程优先级 通过getsetPriority
默认是5 10最高 1最小
守护线程 备胎线程 普通线程完毕后这个线程也会退出
setDaemon(boolean) 开启为true
关于锁synchronized
锁的对象可以是类的class对象 因为是唯一的
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率
可以把synchronized锁起来的代码块 抽取封装成方法 然后用synchronized static去修饰方法
这样的话更加直观 synchronized方法锁的对象就是类名.class
synchronized在非静态方法中锁定的当前对象 即this.class
在静态方法是锁类对象 类名.class
关于lock
Lock是接口不能直接实例化,我们采用它的实现类ReentrantLock来实例化
lock是获得锁 unlock是释放锁
实际上跟synchronized的使用方式一样 然后也是同样的作用
只不过lock锁看起来更加直观
关于死锁
线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行
关于生产者消费者
wait表示让线程等待 notify()唤醒正在等待的单个线程 notifyall()唤醒全部
线程分为两种 生产数据跟消费数据的 还有一个共享数据区
生产者首先会去判断数据区有没有数据 如果有的话等待,没有就执行
生产完数据之后进行等待,唤醒消费者进行消费数据
消费者首先会判断数据区有没有数据,如果有的话就执行,没有的话就等待
消费完数据之后更新数据区是数据,然后唤醒生产者 然后进入等待
关于阻塞队列
就是线程取不到数据会进行等待. 队列可以自定义数量,如果多线程进行
达到阻塞队列的最大数量那么就其他等待的线程就不会进入阻塞队列
直接被抛弃
关于线程池
就是用来更好的管理线程,规定阻塞队列列
不用我们每次都自己去创建线程,有空闲线程的数量
这样的话提高效率