Java 7 新特性 和 一丢丢Servlet 3.X
Java 7 新特性 和 一丢丢Servlet 3.X
Java 7 的基本新特性
参考资料:
https://www.ibm.com/developerworks/cn/java/j-lo-jdk7-1/
Java 语言特性增强(JSR334)
一些提高Java开发效率的改进
Switch 语句中允许使用String类型了:
String myString = "xiaohang";
switch(myString) {
case "xiao":<do something>; break;
case "hang": <do something>; break;
default:<do something>;
}
对通用类型实例的创建提供类型推理[简化代码]:
Java 6: Map<String,MyType> foo = new Map<String,MyType>();
Java 7: Map <String,MyType> foo = new Map<>();
二进制常量和数字常量示例:
可以使用二进制表示值
int anInt1 = 0b10100001010001011010000101000101; //z值:-1589272251
可以使用下划线分隔
int million = 1_000_000; //值:1000000
自动的资源管理机制 :
//try块中的会在之后释放资源【调用close方法】 如InputStream,Writes,Sockets,Sql classes等
try(InputStream inFile = new FileInputStream(aFileName);
OutputStream outFile = new FileOutputStream(aFileName);
) { byte[] buf = new byte[BUFi_SIZE];
int readBytes;
while ((readBytes = inFile.read(buf)) >= 0)
inFile.write(buf, readBytes);
}
I/O APIs(JSR203):
表示I/O这一块不了解啊╮(╯_╰)╭
Java 7 为 Java 开发人员提供了更强大的 I/O 抽象和编程能力,真正的异步 I/O 接口的引入使得 I/O 操作能够被更有效的处理和控制,提供了更好的可扩展性,更灵活的线程池策略。 在 JSR 203 中包含以下的主要组件: 新的文件系统接口、支持大块访问文件属性、更改通知、绕开文件系统指定的 API,也是可插拔文件系统实现的服务提供者接口; 对套接字和文件同时提供了异步 I/O 操作的 API。可被用来建立高可扩展服务器,和多路复用 I/O 不同,异步 I/O 是让客户端启动的一个 I/O 操作, 当操作完成后向客户端发送一个通知,异步 I/O 是通过位于 java.nio.channels 包中的一个接口和类来实现的,所有的 I/O 操作都有下列 2 种形式中的一种:
- 第一个返回 java.util.concurent.Future, 代表等待结果,可使用 Future 特性等待 I/O 操作 ;
- 第二个是使用 CompletionHandler 创建的,当操作结束时,如回调系统,调用这个处理程序。
NIO.2 中所有的异步通道如下:
- AsynchronousFileChannel:读写文件异步通道 ;
- AsynchronousSocketChannel:用于套接字的一个简单异步通道 ;
- AsynchronousServerSocketChannel:用户 ServerSocket 的异步通道,accept() 方法是异步的,连接被接受时,调用 CompletionHandler;
- AsynchronousDatagramChannel:数据报套接字的异步通道 ;
NIO参考资料:Java NIO系列教程(一) Java NIO 概述 【看到六】 【这个是挺重要的东东 如果以后有用到这一块的内容的话】
Java.util.concurent (JSR203)更新 : Fork/Join 框架
参考资料:Fork and Join: Java也可以轻松地编写并发程序
看不懂的资料:https://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/
为实现多核的并发计算的东东
回顾java中的并发:
Java中普通线程的并发:
通过java.lang.Thread和java.lang.Runnable接口来编写,需要确保代码对于共享的可变对象表现出的正确性和一致性,并避免不正确的读写操作,与可能产生的死锁。
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("I am running in a separate thread!");
}
};
thread.start();
thread.join();
这种的写法好像是最初学JAVA的时候学的,这个似乎是1.4版本的样子。在使用多线程同步共享对象的时候,需要使用java.lang.Object.nofity()和java.lang.Object.wait()来实现同步,容易出问题。
Java1.5引入的并发包(1.6中增强):java.util.concurrent
Executors,增强了普通线程(Runnalbe实例被封装了),提供线程池管理和调度策略,其结构可以同步也可异步方式获取。【下面代码是简单的求和】
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;
public class Sums {
static class Sum implements Callable<Long> {
private final long from;
private final long to;
Sum(long from, long to) {
this.from = from;
this.to = to;
}
@Override
public Long call() {
long acc = 0;
for (long i = from; i <= to; i++) {
acc = acc + i;
}
return acc;
}
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
List <Future<Long>> results = executor.invokeAll(asList(
new Sum(0, 10), new Sum(100, 1_000), new Sum(10_000, 1_000_000)
));
executor.shutdown();
for (Future<Long> result : results) {
System.out.println(result.get());
}
}
}
concurrent包中提供了很多的东东,安全队列,细粒度的超时延迟,各种同步模式,支持重入,读写锁,基于轮询的加锁等等:
- 参考资料:http://blog.csdn.net/defonds/article/details/44021605/
- 阻塞队列 BlockingQueue :数组阻塞队列 ArrayBlockingQueue、延迟队列 DelayQueue、链阻塞队列 LinkedBlockingQueue、具有优先级的阻塞队列 PriorityBlockingQueue、同步队列 SynchronousQueue、阻塞双端队列 BlockingDeque、链阻塞双端队列 LinkedBlockingDeque
- 并发Map(映射)ConcurrentMap:ConcurrentHashMap; 并发导航映射 ConcurrentNavigableMap;
- 闭锁 CountDownLatch:一个并发结构,允许一个或多个线程等待一系列指定操作完成。CountDownLatch 以一个给定的数量初始化。countDown() 每被调用一次,这一数量就减一。通过调用 await() 方法之一,线程可以阻塞等待这一数量到达零。
- 栅栏 CyclicBarrier:提供一种同步机制,所有线程需要等待满足栅栏限制等待线程数才能一同继续执行,或者超过设置的超时时间。
- 交换机 Exchanger:提供一种两个线程可以进行相互交换对象的模式。
- 信号量 Semaphore:提供acquire();release() 等方法获取返还信号量等,可用于防止代码一次超过N(信号量)个线程进入。
- 执行器服务 ExecutorService:线程池一样的东东,提供委派执行等的方法。
- 线程池执行者 ThreadPoolExecutor、定时执行者服务 ScheduledExecutorService:这两个都是ExecutorService借口的实现.
- 锁 Lock :java.util.concurrent.locks.Lock ,一个比synchronized 块 更加灵活强大的锁。
- 原子类型 AtomicBoolean,AtomicInteger ,AtomicLong ,AtomicReference :可以用原子方式进行读和写的类型
Java7中引入的ForkJoinPool 进行分叉和合并
ForkJoinPool 与 ExecutorService 相识,是一个特殊的线程池,是为了配合 分叉/合并 任务分割的工作的,其完整的类名为:java.util.concurrent.ForkJoinPool。
分叉和合并的解释:
有点像递归,将任务分割成小块的子任务【多层分叉】,进行并发执行,分叉并不像递归那样是1-1往下,更像是倒树多分叉的情况。
合并则是把子任务的结果返回,如果无返回就等所有任务执行结束即可。【有些分叉是需要子任务的返回结果的】
ForkJoinPool
作为一个特殊的线程池提供使用,可配置并行数量等ForkJoinPool forkJoinPool = new ForkJoinPool(4);
RecursiveAction
作为一种没有任何返回值得任务。只是做一些处理,之后就直接退出了。一个RecursiveAction可以把自己的任务继续拆分为更小块,由独立的线程经常处理。
实例如下:
public class MyRecursiveAction extends RecursiveAction {
private long workLoad = 0;
public MyRecursiveAction(long workLoad) {
this.workLoad = workLoad;
}
@Override
protected void compute() { //核心方法
//if work is above threshold, break tasks up into smaller tasks
if(this.workLoad > 16) {
System.out.println("Splitting workLoad : " + this.workLoad);
List<MyRecursiveAction> subtasks =
new ArrayList<MyRecursiveAction>();
subtasks.addAll(createSubtasks()); //分割
for(RecursiveAction subtask : subtasks){ //执行分割的子线程
subtask.fork();
}
} else {
System.out.println("Doing workLoad myself: " + this.workLoad);
}
}
private List<MyRecursiveAction> createSubtasks() { //按规则分割
List<MyRecursiveAction> subtasks =
new ArrayList<MyRecursiveAction>();
MyRecursiveAction subtask1 = new MyRecursiveAction(this.workLoad / 2);
MyRecursiveAction subtask2 = new MyRecursiveAction(this.workLoad / 2);
subtasks.add(subtask1);
subtasks.add(subtask2);
return subtasks;
}
}
//调用方式:
MyRecursiveAction myRecursiveAction = new MyRecursiveAction(24);
forkJoinPool.invoke(myRecursiveAction);
例子的解释:MyRecursiveAction 将一个虚构的 workLoad 作为参数传给自己的构造子。如果 workLoad 高于一个特定阀值,该工作将被分割为几个子工作,子工作继续分割。如果 workLoad 低于特定阀值,该工作将由 MyRecursiveAction 自己执行。
RecursiveTask
RecursiveTask 是一种会返回结果的任务。它可以将自己的工作分割为若干更小任务,并将这些子任务的执行结果合并到一个集体结果。可以有几个水平的分割和合并。以下是一个 RecursiveTask 示例:
import java.util.ArrayList;
public class MyRecursiveTask extends RecursiveTask<Long> { //此处<long> 为返回结果类型
private long workLoad = 0;
public MyRecursiveTask(long workLoad) {
this.workLoad = workLoad;
}
protected Long compute() { //核心方法
//if work is above threshold, break tasks up into smaller tasks
if(this.workLoad > 16) {
System.out.println("Splitting workLoad : " + this.workLoad);
List<MyRecursiveTask> subtasks =
new ArrayList<MyRecursiveTask>();
subtasks.addAll(createSubtasks()); //拆分
for(MyRecursiveTask subtask : subtasks){ //执行
subtask.fork();
}
long result = 0;
for(MyRecursiveTask subtask : subtasks) { //循环取值
result += subtask.join();
}
return result; //返回值
} else {
System.out.println("Doing workLoad myself: " + this.workLoad);
return workLoad * 3;
}
}
private List<MyRecursiveTask> createSubtasks() {
List<MyRecursiveTask> subtasks =
new ArrayList<MyRecursiveTask>();
MyRecursiveTask subtask1 = new MyRecursiveTask(this.workLoad / 2);
MyRecursiveTask subtask2 = new MyRecursiveTask(this.workLoad / 2);
subtasks.add(subtask1);
subtasks.add(subtask2);
return subtasks;
}
}
//调用方式:
MyRecursiveTask myRecursiveTask = new MyRecursiveTask(128);
long mergedResult = forkJoinPool.invoke(myRecursiveTask);
System.out.println("mergedResult = " + mergedResult);
MyRecursiveTask 示例也会将工作分割为子任务,并通过 fork() 方法对这些子任务计划执行。
此外,本示例还通过调用每个子任务的 join() 方法收集它们返回的结果。子任务的结果随后被合并到一个更大的结果,并最终将其返回。对于不同级别的递归,这种子任务的结果合并可能会发生递归。
ForkJoinPool 的备注说明
- 这个东东,看着感觉高大上的样子,认真想想发现没啥用处,1.6版本的ExecutorService相对来说已经很强大了,而且更加灵活。
- 这个ForkJoinPool个人感觉只有在实现特定算法需要的情况下才会使用到。可以我不会写算法,太难的东东了╮(╯_╰)╭
- 貌似并非每个人都对 Java 7 里的 ForkJoinPool 满意:一个 Java 分叉-合并 带来的灾祸 【这个说的这个新的东东的效率和使用都是渣渣。。(ノ`Д)ノ】
其他一些东东
- 图形界面客户端: Swing 的 Nimbus 外观 ,修饰器JLayer 等
- 安全 / 加密 :椭圆曲线加密算法 (ECC),TLS 密钥重新协商机制 等
- 数据库连接 (JDBC):支持了规范 JDBC 4.1 和 Rowset 1.1。
- 新异常捕获:前面 自动的资源管理机制 就使用了这个新语法。
- Java 2D :对于现代 X11 桌面系统,提供了基于 XRender 的渲染管线
Servlet 3.X 详解
发现3.X的版本其实好像没什么差别,3.0和3.1 。这里就稍微整理一下:
Servlet 3.0 笔记提到的东东
- 异步处理支持 【使Servlet线程资源得到释放,线程本身返回容器,启动异步线程完成业务处理】
- 新增的注解支持 【使部署文件web.xml内的声明可以标签注释即可】
- 可插性支持 【支持在jar中进行对项目的声明配置Servlet/过滤器/监听器等】
- HttpServletRequest 对文件上传的支持 【其实没啥用,已经有解决方案的了╮(╯_╰)╭】
- ServletContext 的性能增强 【实现代码加载Servlet、过滤器、监听器】
补充一丢丢东东
- API改进
- 比如提供HttpOnly支持、HttpServletRequest#getRequestedSessionId直接获取请求时的会话ID、HttpServletResponse#getStatus等直接获取响应状态码、响应头等信息
- 比如Servlet3.1的request/response#getContentLengthLong得到long型内容长度、ServletContext#getVirtualServerName得到虚拟主机名
- 比如Servlet3.1的通过HttpServletRequest#changeSessionId()直接更改会话ID,并可以通过HttpSessionIdListener监听
- 等等
- 获取静态资源 :可以直接获取Jar包里的/META-INF/resources下的资源(包括jsp)
- servlet 3.1的协议升级支持 :使用HttpServletRequest.upgrade和HttpUpgradeHandler实现HTTP/1.1协议升级,如升级到Websocket等等
- pjax与bigpipe
- 使用pjax(ajax + pushState) 无刷新ajax(并能记录ajax加载的历史记录)加载内容
- 使用bigpipe并发加载页面片段,并使用springmvc抽象bigpipe,简化bigpipe开发,可以基于此完善的更易使用
备注说明
- servlet3.1目前仅glassfish支持,在运行servlet3.1的程序时,请使用glassfish maven插件运行。
参考资料:
- https://github.com/zhangkaitao/servlet3-showcase
- 详情请参考:JavaEE7 Servlet 3.1(JSR 340)规范中文版
- 小杭博客-Servlet3.0特性详解-笔记
2017-07-28
小杭
本文来自博客园,作者:小-杭,转载请注明原文链接:https://www.cnblogs.com/xiaohangblog/articles/16296544.html
欢迎转载小杭的博客,记得关注点赞收藏哦 (#^.^#)