3.2 java高级特性

3.2.1 lambda

定义:lambda是匿名函数,基于数学中的λ演算得名。可使代码更加简洁。

Lambda表达式的语法
基本语法:
(parameters) -> expression

(parameters) ->{ statements; }

示例参考地址:Java Lambda表达式入门_java ->{-CSDN博客

                      https://blog.csdn.net/weixin_36755535/article/details/131350405

3.2.2 stream

就是一个“流”类

参考资料:Java--Stream流详解_java stream-CSDN博客

针对某个list中元素的非String属性提取出来组成逗号分隔的字符串

String collect = users.stream().map(User::getId).map(String::valueOf).collect(Collectors.joining(","));

3.2.3 流式编程

基于Stream类对集合进行一系列操作

参考资料:https://blog.csdn.net/JokerLJG/article/details/122693051

3.2.4 函数式编程

定义:函数式编程是一种编程规范,也就是如何编写程序的方法论,属于结构化编程的一种,主要思想是将运算过程尽量写成一系列嵌套的函数调用。

优点:代码简洁,开发快速;接近自然语言,易于理解;更方便代码管理;易于并发编程;代码热升级

参考资料:百度百度-函数式编程

参考资料:Java 函数式编程_java new thread-CSDN博客

Supplier接口:获得结果

  • T get():获得结果
  • 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
  • Supplier 接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用

Consumer接口:对参数进行指定的处理
Consumer:包含两个方法

void accept(T t):对给定的参数执行此操作
default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
Consumer 接口也被称为消费型接口,它消费的数据类型由泛型指定

 Predicate接口

boolean test(T t) 对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值

Function接口

Function<T,R>两个常用方法

R apply(T t)  将此函数应用于给定的参数

default Function<T,V> andThen(Function after) 返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果

3.2.5 反应式编程

定义:反应式编程是一种编程思想、编程方式,为了简化并发编程而出现的。与传统处理方式相比,可基于数据流中的事件进行反应处理。

反应式编程更强调异步非阻塞。

参考资料:https://blog.csdn.net/qq_42799615/article/details/111235576

3.2.6 线程池

线程池概念:创建java线程需要给对象分配栈堆内存和初始化内存,频繁的创建和销毁线程会大大降低系统的运行效率,采用线程池可提升性能(线程池独自负责线程的创建、维护、分配)和更好的管理线程(每个线程池会保存一些基本的线程信息,对线程进行管理)。

JUC线程池架构:

Executor(接口)、ExecutorService(接口)、AbstractExecutorService(抽象类)、ThreadPoolExecutor(JUC线程池核心实现类)、ScheduledExecutorService(延时性和周期性的接口)、ScheduledThreadPoolExecutor(延时执行和周期执行类)、Executors(静态工厂类、调用静态方法获取线程池实例对象)

Executors创建线程的4中方法:

单线程化线程池:按照提交次序顺序执行;唯一线程存活时间无限;适用于任务提交按照次序,任务逐一进行的场景。

缺点:阻塞队列无界,如果队列很大,很有可能导致JVM出现OOM(内存资源耗尽)

ExecutorService executorService = Executors.newSingleThreadExecutor();

固定数量线程池:线程数量固定,如果没有达到固定的线程数量,如果有新的任务进来,会开辟新的线程,直至达到规定的线程数量;线程一旦达到固定数量就会保持不变,如果某个线程因异常而结束,会补充新的线程;如果所有线程处于繁忙,新任务会将进入阻塞队列中。

适用于需要任务长期执行和CPU密集型任务。

缺点:内部使用无界队列来存放排队任务,当大量任务超过线程池最大容量需要处理时,队列无限增大,使服务器资源迅速耗尽

ExecutorService executorService1 = Executors.newFixedThreadPool(3);

可缓存线程池:有新任务进来时,如果所有线程繁忙,则会开辟新的线程;线程池大小不会限制,依赖与JVM或操作系统能创建的最大线程大小;如果部分线程空闲(60秒不执行任务)则会进行回收线程。

适用于快速处理突发性强、耗时较短的任务场景。例如REST API的瞬时削峰场景。

缺点:线程池没有最大线程数量限制,如果大量异步任务执行目标实例同时提交,可能会因线程创建过多导致CPU资源耗尽。

ExecutorService executorService = Executors.newCachedThreadPool();

可调度线程池:延时性、周期性

ScheduledExecutorService pool=Executors.newScheduledThreadPool(2);

pool.scheduleAtFixedRate(new MyThread(), 0, 500, TimeUnit.MILLISECONDS);

缺点:线程数无上限

Executors创建线程存在的问题:

单线程线程池、固定线程线程池:阻塞队列无界,会堆积大量任务导致OOM

可缓存线程池、可调度线程池:  线程数量无限制,会创建大量线程导致OOM

可直接使用线程池ThreadPoolExecutor的构造器。

线程池任务调度流程:

当前线程工作数量小于核心线程数量,则优先创建线程

线程池中任务数量大于核心线程数量,新任务被加入阻塞队列中,直到阻塞队列加满为止

当完成一个任务,执行器优先从阻塞队列中获取任务执行,直到阻塞队列为空

当核心线程用完,阻塞队列已满,会一直创建新线程去执行新任务,直到线程总数超过最大线程数量。

如果池中线程数量超过最大线程数量,线程池会拒绝接收任务,执行拒绝策略。

ThreadFactory称之为线程工厂类,用于创建线程。

Executors称之为线程池工厂类,用于创建线程池。

线程工厂:ThreadFactory是线程工厂接口,只有一个方法newThread,调用此方法时可更改线程的名称、线程组、优先级、守护线程等

任务阻塞队列:线程从空阻塞队列中获取元素时,线程会被阻塞,直至阻塞队列有元素,被阻塞线程会自动执行。

调度器钩子方法:前置钩子、后置钩子、线程池终止时钩子。分别是beforeExecutor、afterExecutor、terminated方法。

线程池拒绝策略:拒绝情况包括线程池关闭、工作队列和线程池最大线程容量都满。

       常见的几种拒绝策略:

AbortPolicy:有新任务就会被拒绝,并且抛出RejectedExecutionException。默认策略

DiscardPolicy:抛弃策略。有新任务直接丢掉,并无异常

DiscardOldestPolicy:抛弃最早进入队列的任务,从队列中腾出空间,加入新的队列

CallerRunPolicy:调用者执行策略。新任务进入线程池失败,则提交任务线程会自己去执行任务,不会使用线程池中的线程。

自定义策略:编写类,实现RejectExecutionException接口,重写rejectedExecution方法

线程池关闭:

       线程池5种类状态:

              RUNNING:创建之后初始化状态,可执行任务

              SHUTDOWN:此状态不会接收新任务,但是队列中的任务会执行完毕

              STOP:不接受新任务、中断未处理任务、中断所有工作线程

              TIDYING:所有任务已结束或处理完成,将会执行terminated方法

              TERMINATED:执行完terminated方法之后的状态

参考资料:https://blog.csdn.net/qq_43478694/article/details/123385279

3.2.7 异步编程

定义:就是将业务中关联性不强的进行拆分,使其同时执行,是程序并发运行的一种手段,允许多个事件同时发生,当程序调用需要长时间运行的方法时,它不会阻塞当前的执行流程,程序可以继续运行。

异步处理是不用阻塞当前线程来等待处理完成,而是进行后续操作,直至其他线程处理结束,回调通知此线程。

异步、多线程、并行并非相同概念。

多线程是对CPU剩余劳动力的压榨,是一种技术,强调的是并发。

异步强调的是非阻塞,是一种编程模式。

并行虽然也是对CPU剩余劳动价值的压榨,且基于多线程入伍,但它强调的是高效完成计算任务,而不是并发数量。

并发和并行的区别:并发强调的是有处理多个任务的能力;并行强调的是有同时处理多个任务的能力。

最简单使用异步编程的方式就是创建1个线程来实现。

参考资料:https://blog.csdn.net/m0_58821619/article/details/117979239

              https://www.zhihu.com/question/33515481/answer/58849148

              https://blog.csdn.net/AS011x/article/details/126931651

3.2.8 网络编程AIO/NIO/BIO

同步定义:多线程并发访问共享数据时,保证共享数据在同一时间只被一个线程使用。

BIO:同步阻塞IO。此网络编程基本模型是C/S模型,即两进程之间的通信。此模型最大问题是缺乏弹性伸缩能力,客户端访问量激增后,服务端线程和客户端呈1:1的正比关系,随着访问量持续增大,其他接入的消息,只能一直等待,甚至系统会死掉。

NIO:非阻塞IO。支持阻塞和非阻塞两种形式。NIO提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。

相对高负载、高并发的网络应用,更适合非阻塞IO来开发。

缓冲区buffer:一个包含写入或读取数据的对象;在NIO库中,所有数据都是在缓冲区处理的;缓冲区实际上是一个数组,并提供了对数据结构化访问和维护读写位置等信息;

具体的缓冲区有:ByteByffer、CharBuffer、ShortByffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。都实现了Buffer接口。

通道channel:数据的读取和写入需要经过channel。就像一个双向通道,可用于读、写、读写同时操作。

       channel分两类:

              SelectableChannel:用户网络读写

              FileChannel:用于文件操作

       SocketChannel和ServerSocketChannel都是SelectableChannel的子类。

多路复用器Selector:是NIO编程的基础。Selector提供选择就绪任务的能力,会不断轮询注册在其上的channel,如果某个channel上发生读写事件,就会被selector轮询出来,然后通过SelectionKey获取就绪channel的集合,进行后续的I/O操作。一个Selector可以同时轮询多个channel。因此只需要一个线程负责Selector的轮询,就可以接入成千上万客户端。

事件驱动IO:AIO

NIO的2.0版本,引入了异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

异步套接字通道,是真正的异步非阻塞IO。无需过多的Selector对注册的通道进行轮询即可实现异步读写,简化NIO的编程模型。

参考资料:Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)_java bio-CSDN博客

              https://blog.csdn.net/qq_35190492/article/details/113174359

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值