多线程的概述
假如一个程序有多条执行流程,那么,该程序就是多线程程序。
多线程概述:
进程:
正在运行的程序,是系统进行资源分配和调用的独立单位。
每一个进程都有它自己的内存空间和系统资源。
线程:
是进程中的单个顺序控制流,是一条执行路径
一个进程如果只有一条执行路径,则称为单线程程序。
一个进程如果有多条执行路径,则称为多线程程序
多线程的好处:同一段时间cpu可以完成多个任务,cpu在执行各个任务时在进行高效切换,提高cpu的使用效率。
java中的多线程:是Java虚拟机调用C和C++的程序封装实现的
多线程实现方式:
方式一:继承Thread:
1.自定义类继承thread类
2.重写Run方法
3.创建对象
4.启动线程(常用方法:run、start)
常用方法:getName();setName(); static Thread.currentThread()
优先级(默认5<1-10>)有关方法:getPriority();setpriority() ;
优先级仅仅表示一个获取时间片的概率性
休眠:static sleep(long time); **—抛异常 可打断
加入:join();(阻塞当前线程,在哪个位置加入就在哪个位置阻塞,<龟兔赛跑的一种解决思路>先让加入的一些线程走完)—抛异常 可打断
礼让:static yield();(几乎交替执行比较和谐)
守护(后台):setDaemon(boolean on);(坦克大战中的主坦克和守护坦克)
中断:final void stop(); void interrrupt();(system.in.read() 打断子线程)—**未休眠 也可以被打断
总结:
1、重写run()是为了标识哪些代码需要线程执行,但是run方法单独调用就相当于调用普通方法,必须调用start()面试run只是调用里面的代码,start是先启动线程,再由JVM调用run方法。
2、创建的两个线程对象各自有自己的成员属性(资源)适合资源不共享的多线程问题
方式二:实现Runnable接口
1.自定义类实现接口
2.重写run()方法
3.创建实现类对象
4.创建Thread类对象,把实现类对象作为构造参数传递
公有的资源可以通过实现类的构造方法传值
好处:1.解决单继承(有了父类不能再继承thread,除非父类继承此类,
但是父类不想继承)的局限性 处理多线程公用同一资源
多个相同程序处理同一资源,数据有效分离,体现了面向对象的思想
2.不将对象给thread 是main线程调方法
3.适合匿名内部类实现 访问当前线程需要使用静态方法
4.耦合性低
资源不共用,用static变量也出现资源问题
线程安全
线程安全问题出现的因素:
1.是否多线程环境
2.是否数据共享
3.是都多条语句操作共享数据
解决思路:------------->同步机制
把多条语句操作共享数据的代码当做一个整体包起来,只能当前线程执行
{
{
同步的关键字:synchronized(对象)
不同的语句琐对象不一样:
同步代码块:任意唯一对象
同步方法:this
静态同步方法:类.class
}
{
LOCK锁的引入:
子类:reentrantLock 方法:lock();unlock();
功能更强大,加锁解锁位置明确,配合rty finally使用
}
}
弊端:
1.每次线程都要进行大量判断,效率低,安全低效
2.如果出现了同步嵌套,会出现死锁现象(因为争抢资源而出现的互相等待问题,锁还没释放,就有线程需要此锁,且互相等待)
线程通信问题: 不同线程对同一资源操作
1.第一个线程的执行不确定,如果在生产者还未产生数据时,消费者就开始操作数据,会出现数据为空的情况。-------------->等待唤醒机制(老方法被新方法取代)
2.操作数据时不是原子性的操作,导致当前线程和其它线程一块对数据进行操作,出现安全问题
具体方法:object 类的三个方法:notify(); notifyAll();
writ() :在哪里等待就在哪里醒来 睡眠同时释放cpu和锁和sleep只释放cpu不放锁,不通信 **—**抛异常 可打断
因为琐对象是任意的,所以定义在Object类。
生产者消费者解决:
1.生产和消费都在另一个连接类中封装为了功能,并加了同步
2.生产消费线程只需要调用就行