前面有一篇文章写的是多线程的基本知识,以及线程实现的两种方式,一种是继承Thread类,另一种实现Runnable 接口,今天沿着前面的多线程,继续分享多线程的第三种创建方法,以及第三种创建方法的优势,前两种方法的弊端。并且介绍一种新的线程同步机制:lock锁的机制。
1. 实现线程的第三种方式:
实现 Callable 接口,重写 call 方法.
2. 继承Thread类,实现Runnable 接口实现多线程的弊端:
(1) 没有返回值
(2) 不支持泛型
(3) 异常必须处理
3. Callable 强大在哪里呢?
(1) Future 接 口 位 于 java.util.concurrent 包 中 ,可 以 对 具 体Runnable、Callable 任务的执行结果进行取消(cancel 方法,尝试取消执行此任务)、查询是否完成(isDone 方法)、获取结果(get 方法,等待完成,然后检索其结果)等。
(2) FutrueTask 是 Futrue 接口的唯一的实现类.
(3) FutureTask 同时实现了 Runnable, Future 接口。它既可以作为 Runnable 被线程执行,又可以作为 Future 得到Callable 的返回值.
4. 线程同步的第三种方法:Lock锁。
Lock 锁:对需要上锁的地方上锁
1) JDK1.5 后新增的功能
2) 与 Synchronized 相比,Lock 可提供多种锁方案,更灵活
3) Java.util.concurrent.locks 中的 Lock 是一个接口,它的实现类是一个 Java 类,而不是作为语言的特性(关键字)来实现。
注意:如果同步代码有异常,要将 unLock()放到 finally 中。
4. 1 创建Lock锁的步骤。
(1) 创建 Lock 对象
(2) 调用 lock()方法上锁
(3) 调用 unlock()方法解锁
4.2 Lock 与 synchronized 的区别。
(1) Lock 是 显 示 锁 (手 动 开 启 和 关 闭 锁 ,别 忘 关 闭锁),synchronized 是隐式锁
(2) Lock 只有代码块锁,synchronized 有代码块锁和方法锁。
(3) 使用 Lock 锁,JVM 将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)。
(4) Lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。lock()方法会对 Lock 实例对象进行加锁,因此所有对该对象调用 lock()方法的线程都会被阻塞,直到该 Lock 对象的 unlock()方法被调用。
5. 线程池。
5.1 什么是线程池?
创建和销毁对象是非常耗费时间的
创建对象:需要分配内存等资源
销毁对象 :虽然不需要程序员操心,但是垃圾回收器会在后台一直跟踪并销毁对于经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路 :创建好多个线程,放入线程池中,使用时直接获取引用,不使用时放回池中。可以避免频繁创建销毁、实现重复利用。
5.2 线程池的好处.
(1) 提高响应速度(减少了创建新线程的时间)
(2) 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
(3) 提高线程的可管理性:避免线程无限制创建、从而销毁系
统资源,降低系统稳定性,甚至内存溢出或者 CPU 耗尽
5.3 线程池的应用场合
(1) 需要大量线程,并且完成任务的时间短。
(2) 对性能要求苛刻。
(3) 接受突发性的大量请求。
6. 任务调度 度 Task_Timer和 ThreadLocal。
6.1 什么是调度?
任务:就是事情
调度:在不同的时间点或者在指定的时间点或者间隔多长时间我去运行这个任务。
类似于生活中的闹钟。
6.2 ThreadLocal.
ThreadLocal 直译为“本地线程”,其实它就是一容器,用于存放线程的局部变量
作用:为解决多线程程序的并发问题。
谢谢大家,共同努力,共同进步。