JAVA 多线程,安全锁总结
1、多线程应用场景:
①需要同时执行最少两个以上任务。
②程序需要有等待任务,例如:文件读写,网络操作,搜索。
③后台运行程序。
2、多线程程序的优点:
①提高程序的响应,对图形化界面更有意义,可增强用户体验。
②提高系统CPU的利用率
③改善程序结构。将又长又复杂的进程分为多个线程,独立运行,便于修改和处理。
3、创建多线程方式一:Thread
①创建一个继承Thread的子类
②重写Thread类的run方法
③创建Thread类的子类对象
④通过此对象调用start()
4、Thread常用方法:
①currentThread():静态方法,返回执行当前代码的线程
②start():启动当前线程,调用当前线程的run()
③run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
④getName():获取当前的线程名Thread.currentThread().getName()
⑤setName():设置当前的线程名
⑥yield():释放当前CPU的执行权限
⑦join():在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。
⑧sleep(long millitime):当前线程进入“睡眠”的millitime毫秒,在millitime毫秒时间内,线程是阻塞状态。
⑨isAlive():判定当前线程状态是否存活
5、Tread优先级:
①MAX_PRIORITY 线程最高是10
②MIN_PRIORITY 线程最低是1
③NORM_PRIORITY 默认是5
④getPriority 获取线程优先级数
⑤setPriority 设置线程有限级数
说明:优先级高可以抢占有限级低的线程CPU执行权,但是并不是先执行完优先级高的在执行优先级低的线程,概率高而已
6、创建多线程方式二:Runnable接口
①创建一个实现Runnable接口类
②实现类去实现Runnable中的抽象run()方法
③创建实现类的对象
④将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
⑤通过Thread类的对象调用start()方法
7、比较两种多线程创建方式:开发中优先选择Runnable接口方式
原因:①实现的方式没有类的单继承性局限性
②实现的方式更适合来处理多线程共享数据情况
联系:public class Thread implements Runnable
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
8、生命周期:
①新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
②就绪:处于新建状态的线程被start()方法后,将进入线程队列等待CPU时间片,此时它已经具备运行条件,只是没有分配到CPU资源
③运行:当就绪的线程被被调度并分配CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能
④阻塞:在某种情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态
⑤死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致
9、多线程安全:
方式一:同步代码块
synchronized(同步监视器){
//需要同步的代码
}
说明:①操作同步数据的代码,即为需要被同步的代码
②共享数据:多个线程共同操作的变量。
③同步监视器,俗称:锁,任何一个类的对象,都可以充当锁。
要求:多个线程必须使用同一把锁。
补充:在实现Runnable接口创建多线程时,可以考虑用this充当同步监视器
方式二:同步方法
非静态同步方法:
private synchronized void run(){
//需要同步的代码
}
静态同步方法:
private static synchronized void run(){
//需要同步的代码
}
说明:
①同步方法仍然设计到同步监视器,有默认方法,不用显示声明
②非静态方法同步监视器是:this
静态方法同步监视器是:当前类本身
好处:同步的方式解决了线程的安全问题
缺陷:操作代码时,只能有一个线程参与,其它线程等待。相当于是一个单线程的过程,效率低
方式三:lock锁 --JDK5.0新增
ReentrantLock r = new ReentrantLock();
r.lock(); //加锁
//线程安全区代码
r.unlock(); //解锁
10、多线程死锁:
死锁:不同的线程分别占用对方需要的资源不放弃,都在等待对方放弃自己需要的资源,形成了线程的死锁
解决方法:
①专门的算法、原则
②尽量减少同步资源的定义
③尽量避免嵌套同步
11、线程通信:
三个方法:
wait():执行此方法,线程进入阻塞状态,并释放同步监视器
notify():执行此方法,唤醒wait()的一个线程;如果有多个线程唤醒优先级最高的,优先级一样随机唤醒
notifyall():执行此方法,唤醒wait()所有线程
说明:三个方法必须使用在同步代码块或同步方法中
三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现异常
三个方法定义在Java.long.Object类中
12、创建多线程方式三:实现Callable接口
创建步骤:①创建一个实现Callable的实现类
②实现call()方法,将此线程需要执行的操作声明在call()中
③创建callable接口实现类的对象
④将此callable接口实现类的对象作为传递到FutureTask
⑤将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
⑥获取callable中call方法的返回值
13、创建多线程方式四:使用线程池
好处:①提高响应速度(减少创建线程的时间)
②降低资源消耗(重复利用线程,不需要每次重新创建)
③便于线程管理