多线程基础
线程
进程
进程是操作系统结构的基础;是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位
什么是线程?
线程可以理解成是在进程中独立运行的子任务
实现多线程的主要两种方式:
一种是继承Thread类,另一种是实现Runnable接口
(全部有4种,这里只讲解最常用的两种)
继承Thread类,重写run方法,在线程执行时调用start方法
从运行上看,总是end先运行,因为MyThread创建线程需要时间,创建的过程中end已经运行完了,也就是说,运行结果和代码的执行顺序是无关的。
实现Runnable接口,同样的也是要实现run方法
使用继承Thread是有局限性的,因为Java是单重继承的,使用实现Runnable的方法实现多线程,类还能继续扩展父类
多个线程访问,就会出现非安全的问题,解决共享数据的安全问题
运行的结果
添加synchronized在方法前面,解决变量不安全问题
synchronized可以在任意对象及方法上加锁,而加锁的这段代码成为“互斥区”或“临界区”。给线程加了一把锁,只有拿到这把锁,才能运行synchronized里的代码,拿到的线程运行完后会释放锁,没有拿到的线程会不断尝试去拿锁,直到拿到为止。
线程的一些方法
currentThread方法
可以返回代码段正在被哪个线程调用的信息
sleep方法
在指定的毫秒时间内让运行状态的线程休眠
getId方法
取得线程的唯一标识符
线程停止
使用退出标志,使线程正常退出,当run方法完成后线程终止
使用stop方法强行终止线程,但是不推荐,stop方法和suspend、resume方法都是过期的方法,使用它们可能产生不可预料的结果
- 使用interrupt方法中断线程
使用interrupt方法中断当前线程
interrupted方法检验线程是否已经中断
第一次返回true,第二次返回false。
那是因为interrupted方法具有清除状态的功能,所以第二次调用interrupted方法的返回值是false
使用isInterrupted方法检验线程是否中断
isInterrupted方法也是检验线程是否已经中断,但不清除状态标志
- 异常停止线程
- 沉睡中停止
在sleep方法执行的期间,调用interrupt方法,迫使线程停止
- stop方法暴力停止
调用stop方法时会抛出java.lang.ThreadDeath异常
stop方法释放锁将会给数据造成不一致的结果,所以不建议使用stop方法
- suspend与resume方法
suspend暂停线程,暂停意味着还可以恢复运行。使用resume恢复线程
suspend与resume方法,如果使用不当,会造成公共的资源被独占,迫使其他线程无法访问同步资源
也容易出现因为线程暂停而导致数据不同步的情况
- yield方法
放弃当前的CPU资源,把资源让给其他任务。放弃的时间不能确定,有可能刚刚放弃,马上又获得CPU时间片。
- setPriority方法
设置线程的优先级,优先级较高的线程得到的CPU资源较多
高优先级的线程总是先执行完,但不代表高优先级的线程全部执行完才执行低优先级的线程。
线程的优先级具有“随机性”,也就是优先级较高的线程不一定每一次都先执行完
并发访问
synchronized同步
- “非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,就不存在“非线程安全”的问题。
- 如果多个线程访问通一个对象中的实例变量,就可能出现“非线程安全”问题。
- 如果对象仅有一个实例变量,有可能出现覆盖的情况。
- 当有多个对象出现的时候,运行的效果是异步的,因为多个对象会出现多个锁。
- synchronized弊端,一个线程调用同步方法执行时间太长,那么等待同步方法的线程也必须要等待。
synchronized同步代码块
- 当两个并发线程访问同一对象中的synchronized(this)同步代码块时,只能有一个线程执行,另一个必须等待当前线程执行完才能执行该代码块
- 当多个线程同时执行synchronized(x){}同步代码块时呈同步效果
- 当其他线程执行x对象中synchronized同步方法时呈同步效果
- 当其他线程执行x对象方法里面的synchronized(this)代码块时也呈同步效果
volatile关键字
volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值
synchronized 和volatile比较:
- 关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。
- 多线程访问volatile不会发生阻塞,而synchronized会出现阻塞
- volatile能保证数据的可见性,但不能保证数据的原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步
- 关键字volatile解决的是变量在多个线程之间的可见性;而synchronized解决的是多个线程之间访问资源的同步性
- 关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或某一个代码块。它包含两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改效果