Java 7 新特性 和 一丢丢Servlet 3.X

Java 7 新特性 和 一丢丢Servlet 3.X

Java 7 的基本新特性

参考资料:
https://www.ibm.com/developerworks/cn/java/j-lo-jdk7-1/

http://www.oschina.net/news/20119/new-features-of-java-7

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 框架

参考资料:JDK 7 中的 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插件运行。

参考资料:


2017-07-28
小杭


posted @ 2022-05-21 23:35  小-杭  阅读(25)  评论(0编辑  收藏  举报