模板方法
模板方法模式定义:
定义一个操作的算法骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可定义该算法的某些特定步骤。
12345678910111213141516171819202122232425262728public class TemplateMethod { public static void main(String[] args) { AbstractClass abstractClass = new SubClass(); abstractClass.operation(); }}abstract class AbstractClass{ public void operation(){ System.out.println("pre handle"); System.out.println("step1."); templateMe ...
JUC并发编程十二(CompletableFuture)
12 CompletableFuture12.1 CompletableFuture简介CompletableFuture在Java里面被用于异步编程,异步通常意味着非阻塞,可以使得我们的任务单独运行在与主线程分离的其他线程中,并且通过回调可以在主线程中得到异步任务的执行状态,是否完成,和是否异常等信息。
CompletableFuture实现了Future,CompletionStage接口,实现了Future接口就可以兼容现在有线程池框架,而CompletionStage接口才是异步编程的接口抽象,里面定义多种异步方法,通过这两者集合,从而打造出了强大的CompletableFuture类。
12.2 Future和CompletableFutureFuture在Java里面,通常用来表示一个异步任务的引用,比如我们将任务提交到线程池里面,然后我们会得到一个Future,在Future里面有isDone方法来判断任务是否处理结束,还有get方法可以一直阻塞知道任务结束然后获取结果,但整体来说这种方式,还是同步的,因为需要客户端不断阻塞等待或者不断轮询才能知道任务是否完成。
Futu ...
JUC并发编程十一(Fork/Join)
11 Fork/Join11.1 Fork/Join 框架简介Fork/Join它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。Fork/Join框架要完成两件事情:
12Fork: 把一个复杂任务进行拆分,大事化小Join:把分拆任务的结果进行合并
1.任务风格:首先Fork/Join框架需要把大的任务分割成足够小的子任务,如果子任务比较大的话还要对子任务进行继续分割
2.执行任务合并结果:分割的子任务分别放到双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都放在另外一个队列里,启动一个线程从队列里取数据,然后合并这些数据。
在Java的Fork/Join框架中,使用两个类完成上述操作。
ForkJoinTask:我们使用Fork/Join框架,首先需要创建一个ForkJoin任务。该任务提供了在任务中执行fork和join的机制。通常情况下我们不需要直接继承ForkJoinTask类,只需要继承它的子嘞,Fork/Jo ...
JUC并发编程十(Thread Pool线程池)
10 ThreadPool线程池10.1 线程池简介线程池:一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配颗并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能保证内核的充分利用,还能防止过度调度。
例子:10年前单核cpu电脑,假如多线程,像马戏团小丑玩多个球,cpu需要来回切换。现在是多核电脑,多个线程各自跑在独立的cpu上,不用切换效率高。
线程池的优势:线程池做的工作只要是控制运行的线程数量,在处理过程中将任务放入队列,然后知啊线程创建后启动这些任务,如果线程数量超过了最大数量,超过数量的线程排队等候,等待其他线程执行完毕,再从队列中取出任务来执行。
它的主要特点为:
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行。
提高线程的可管理性:线程时稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
Java中的线程池是通过Executor ...
JUC并发编程九(阻塞队列)
9 阻塞队列9.1 BlockingQueue 简介Concurrent包中,BlcokingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速戴安高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的锁欧成员,包括他们各自的功能以及常见使用场景。
阻塞队列,故名思义,首先它是一个队列,通过一个共享的队列,可以是的数据由队列的一段输入,从另一端输出;
当队列是空的,从队列中获取元素的操作将会被阻塞
当队列是满的,从队列中添加元素的操作将会被操作
试图从空的队列获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素
试图向已满的队列添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增
常见的队列主要有以下两种:
先进先出(FIFO):先出入的队列的元素也最先出 队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。
后进后出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件(栈)
在多线程领域:所谓 ...
JUC并发编程八(读写锁)
8 读写锁8.1 读写锁现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。
针对这种场景:JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁
1.线程进入读锁的前提:
没有其他线程的写锁
没有写请求,或者==有写请求,但调用线程和持有锁的线程是同一个(可重入锁)。==
2.线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
而读写锁有以下三个重要的特性:
(1)公平选择性:支持非公平(默认)和公平锁的获取方式,吞吐量还是非公平优于公平。
(2)重进入:读锁和写锁都支持线程重进入。
(3)锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。
8.2 ReentrantReadWriteLock123456789 ...
JUC并发编程七(JUC三大辅助类)
7 JUC三大辅助类JUC中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时Lock锁的频繁操作。但三种辅助类为:
CountDounLatch:减少计算
CyclicBarrier:循环栅栏
Semaphore:信号灯
7.1 减少计数CountDownLatchCountDownLatch 类可以设置一个计数器,然后通过 countDown 方法来进行减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法之后的语句。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞
其他线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞)
当技术器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行
场景:6个同学陆续离开教室后同学才可以关门。
12345678910111213141516171819202122232425262728public class CountDownLatchDemo { public static ...
JUC并发编程六(Callable&Future接口)
6.Callable&Future接口6.1 Callable 接口有两种创建线程的方法-一种是通过创建 Thread 类,另一种是通过使用 Runnable 创建线程。但是,Runnable 缺少的一项功能是,当线程终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能,Java 中提供了 Callable 接口。
==现在我们学习的是创建线程的第三种方案—Callable 接口==
Callable 接口的特点如下(重点)
为了实现Runnable,需要实现不反悔任何内容的run( )方法,而对于Callable,需要实现在完成时返回结果的call( )方法。
call( )方法可以引发异常,而run( )则不能。
为实现Callable而必须实现call方法
不能直接替换runnable,因为Thread类的构造方法根本没有Callable
1234567891011创建新类 MyThread 实现 runnable 接口class MyThread implements Runnable{ @Ove ...
JUC并发编程五(多线程锁)
5 多线程锁5.1 锁的八个问题演示123456789101112131415class Phone { public static synchronized void sendSMS() throws Exception { //停留 4 秒 TimeUnit.SECONDS.sleep(4); System.out.println("------sendSMS"); } public synchronized void sendEmail() throws Exception { System.out.println("------sendEmail"); } public void getHello() { System.out.println("------getHello"); }}
123456789101112131415161 ...
JUC并发编程四(集合的线程安全)
4 集合的线程安全4.1 集合操作DemoNotSafeDemo
12345678910111213public class ClassNotSafeDemo { public static void main(String[] args) { List list = new ArrayList(); for (int i = 0; i < 100; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString()); System.out.println(list); },"线程"+i).start(); } }}
异常类容
java.util.ConcurrentModificationException
问题: 为什么会出现并发修改异常?
查看 Array ...