目录
3.3相比继承Thread,优先使用Runnable接口原因
1.程序,进程,线程,携程
四者联系:
一个运行程序(Program)=一个进程(Process)
一个进程可能存在多个线程(Thread) 同步或异步
一个线程可能存在多个携程(Coroutines)
四者具体功能:
Program 是静态代码
Process 程序的实例,拥有独立地址空间
Thread 调度和执行的最小单位,是进程中一个实体,有独立栈,但共享进程的地址空间;若进程同一时间“并行”执行,即为多线程
补充:并行 指多个CPU同时执行多个任务
并发 指一个CPU同时执行多个任务
2.线程生命周期
3.线程创建和操作方法
作为最小执行单位,拥有Thread父类和Runnable接口,Callable接口
3.1继承Thread类
创建Thread子类,按需求重写run()方法 【run代表此线程执行时会做的事】
这里的属性若为 多线程共享属性,加static修饰
实例化Thread子类
3.2实现Runnable接口
这里的 多线程共享属性 可以是非静态的,因为多线程共用此接口
先实现接口,Thread构造器有 Thread(Runnable){},这样多个线程共用同一个run方法和各属性
但是以上两种方法都会出现线程抢占安全问题
3.3相比继承Thread,优先使用Runnable接口原因
(1)非静态属性也是共享数据
(2)非静态方法可直接用synchronized修饰
3.4实现Callable接口
(1)实现接口Callable,重写call()回调方法,会返回一个值,值类型由Callable泛型决定
(2)实例化上述类,利用FutureTask(Callable)构造器实例化类,最终实例化Thread(FutureTask)以创建线程
(3)特别注意
在实现Callable接口时,抛出了异常,需要我们在使用时try_catch接受异常,通常系统会提示,我们可以让系统帮我们自动生成上去
3.5Thread类操作方法(持续更新)
sleep(millis) 此线程从运行进入阻塞状态 ;millis结束,此线程又回到就绪状态【不释放锁】
join() 在B线程调用A.join(),使得B线程等待A执行完,B线程才能执行【源码使用wait封装,会释放当前线程同步锁】
join(millis) 同上,只是等待一个线程有了最长时间,时间到或者提前执行完才会回到当前线程
wait()线程进入阻塞状态,并释放同步锁
notify() 将 由wait()阻塞线程中优先级最高的那个转为 就绪态
notifyAll() 将所wait()阻塞线程全部转变为 就绪态
getPriority()获取线程优先级
setPriority()设置线程优先级 【优先级为1-10,默认是5;Thread.MIN_PRIORITY为1,Thread.MAN_PRIORITY为10】
Thread.currentThread() 随时获取当前执行线程
getName()获取当前线程名字
setName(String)设置当前线程名字
run() 线程执行的具体任务
start()让线程进入就绪状态,随时准备开始执行
yield()该线程失去CPU,从运行态转为就绪态【不释放锁】
stop()运行的线程死亡
suspend()挂起线程,由执行态转为阻塞态【不释放锁】
resume()恢复被挂起的线程 ,由阻塞态转为就绪态
call() 是Callable接口的回调方法,能在线程执行时执行功能,并返回一个值
4.同步代码块和同步方法解决线程安全问题
4.1继承Thread
同步代码块——》操作共享数据的代码,只允许一个线程正在执行
格式: synchronized{
// 只能同时让一个线程执行的任务
}
注意:synchronized(同步监视器),同步监视器必须唯一,这里不能用this,会代表多个实例化对象,最好用该类的字节码
同步方法格式:
如下图 必须是synchronized修饰的静态方法 ,若无static则同步监视器默认为this,线程不安全
4.2实现Runnable接口
同步代码块:
同步监视器保证唯一性,这里this代表的实现接口的对象,只有一个,也可以用其他唯一的
同步方法:
直接加synchronized修饰
4.3锁是啥,怎么用
锁-》官方名字“同步监视器”,是我们同步代码块和同步方法确定在哪个线程执行的依据
下面我们要学会释放锁
4.3.1 正常途径
同步方法,同步代码块执行结束
同步方法,同步代码块中遇到break,return 提前终止 代码执行
线程对象的wait(),使线程进入阻塞态并释放锁
4.3.2 异常途径
抛出了Error或者Exception未处理【我指的try_catch】,就导致程序异常结束,整个程序直接崩溃掉。。。
4.4总结两策略
注意同步构造器的唯一性 ,(特别注意this在继承Thread时不能用)
同步方法 在继承Thread类模式下,同步方法用static修饰,同步代码块不能用this, 这是保证同步监视器唯一性