多线程知识总结

进程:正在进行的程序。其实进程就是一个应用程序运行时的内存分配空间。
线程:其实就是进程中的一个程序执行控制单元,一条执行路径。
一个进程中至少有一个线程在运行
当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序
每个线程在栈区西欧有自己的执行的空间,自己的方法区、自己的变量。
当产生垃圾的时候,收垃圾的动作不需要主线程来完成。
随机的原理:因为cpu做着快速的切换,哪个线程获取到了cpu的执行权,哪个线程就执行

返回当前线程的名称:thread.currentThread().getName();
线程的名称:thread-编号定义的 编号是从零开始的
线程要运行的代码都统一放在run方法中

线程要运行必须通过类中指定的方法开启。start方法
start方法:1,启动了线程2,让jvm调用run方法

创建线程的第一种方式
1,定义一个类继承thread类
2,目的是覆写run方法。将要让线程运行的代码都放在run方法中
3,通过创建thread类的子类对象,创建线程对象
4,调用线程的start方法开启线程并执行run方法
线程状态
被创建 start()
运行 具备cpu执行权并具备cpu执行资格
冻结 释放cpu执行权并释放cpu执行资格
临时阻塞状态  具备cpu执行资格 不具备cpu执行权
消亡  stop(); interrupt();
第二种创建线程的方法
1,定义类实现runnable接口
2,覆盖接口中的run方法
3,通过thread类创建线程对象
4,将实现了runnable接口的子类对象作为实际参数传递给thread类中的构造函数
为什么传递呢?因为要让线程对象明确要运行的run方法所属的对象
5,调用thread对象的start方法。开启线程,并运行runnable接口子类中的run方法

为什么要有runnable接口的出现
通过几次thread类的方式,可以完成多线程的建立。但是这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承thread类,因为java单继承的局限性。
可是该类中的还有部分代码需要被多个线程同时执行。这个时候该怎么办
只有对该类进行额外功能扩展,java就提供了一个借口runnable。这个借口定义了run方法,其实run方法定义就是为了存储多线程要运行的代码
所以通常创建线程都用第二种方式
因为事先runnable借口可以避免单继承的局限性
其实将不同类中要被多线程执行的代码进行抽取。将多线程要运行的代码的位置单独定义到借口中。为其他的类进行功能的扩展提供了前提
实现runnable借口可以避免单继承的局限性。而且继承thread是可以对thread类中方法,进行子类覆写。但是不需要做这个覆写的动作的话,职位定义线程代码存放的位置,实现runnable借口更加方便一些,所以runnable借口将线程要执行的任务封装成了对象

多线程安全的原因:
通过图解:发现一个线程在执行多条语句的时候并运算同一个数据的时候,其他的线程参与进来并操作了这个数据。导致了错误数据的产生

涉及到两个因素
1,多个线程在操作共享数据
2,有多条语句对共享数据进行运算
原因:这多条语句,在某一个时刻被一个线程执行,还没有执行完,就被其他线程执行
只要将操作共享数据的语句在某一个时间段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决这个问题。
如何进行多语句操作共享数据代码的封装

同步的出现
好处:解决了线程的安全的问题
弊端相对降低性能。因为判断锁需要消耗资源,产生了死锁

定义同步要有前提:
必须要有两个或者两个以上的线程,才需要同步
多个线程必须保证使用的是同一个锁

同步函数:就是将同步关键字定义在函数上,让函数具备了同步性
通过验证,函数都有自己所属的对象this,所以同步函数锁使用的锁就是this锁
当同步函数被static修士,这个同步用的是哪个锁呢
静态在家中所属的类,这时有肯还没产生该类的对象,但是该类的字节码文件加载到内存就已经被封装成了对象,这个对象就是该类的字节码文件对象
所以静态加载时,只有一个对象存在,那么静态同步函数就使用的这个对象
这个对象就是 类名。class

同步代码块和同步函数的区别
同步代码块使用的锁可以任意的对象
同步函数使用的锁是this 静态同步函数的锁是该类的字节码文件对象

在一个类中只有一个同步,可以使用同步函数。如果有多同步,必须使用同步代码块,来确定不同的锁,所以同步代码块相对灵活一些

class single
{

public static Single s = null;
private Single(){}
public static Single getInstance()
{
{Synchronized(Single.class)

if(s == null)
{
Single s = new Single(); 

}
}
return s ;
}

线程间通信
思路:多个线程在操作同一个资源,单操作的动作却不一样
1,将资源封装成对象
2,将线程执行的任务(任务其实就是run方法),也封装成对象

等待唤醒机制
涉及的方法
wait:将同步中的线程处于冻结状态。释放了执行权,释放了资格。统计公式将线程对象存储到线程池中
notify唤醒线程池中的某一个等待线程
notifyall:唤醒的是线程池中所有的线程

注意:1,这些方法需要定义在同步中
2,因为这些方法必须要标示所属的锁
你要知道A锁上的线程都被wait了,那这个超线程就相当于处于A锁的线程池中,只能A锁的notify唤醒
3,这三个方法都需要定义在同步内,并标示所忽视的同步锁,既然被锁调用,而锁又可以是任意的对象,那么能被任意对象调用的方法一定要定义在object类中
wait和sleep的区别
wait可以指定时间也不指定时间。不指定时间,只能由对应的notify或者notifyall来唤醒
sleep必须指定时间,时间到自动从冻结状态转成运行状态
wait:线程会释放执行权,而且线程会释放锁
sleep线程会释放执行权但是不释放锁

线程的停止
通过stop方法就可以停止线程。但是这个方式过时了
停止线程:原理就是让运行的代码结束,也就是结束run方法
怎么结束run方法呢?一般run方法里面肯定定义了循环,只要让循环结束就可以了
第一种方式
定义循环结束的标记
第二种方式
如果现场处于了冻结状态,是不可能读到标记的,这个时候就需要通过thread类中的interrupt方法,将其冻结状态强制清除,让线程恢复具备执行资格的状态,让线程可以读到标记,并结束

interrupt 中断线程
setpriority 更改线程的优先级
tostring()返回线程的字符串表现形式包括线程名称、优先级和线程组
thread.yield()暂停当前正在执行的线程对象 并执行其他线程

join:临时加入一个线程的时候可以使用join方法
当 A线程执行到了B线程的join方法,A线程处于冻结状态释放了执行权,B开始执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值