更多NIO APIs JSR 203:NIO 2扩展和实现了在Java 1.4中加入的最初NIO功能。在NIO 2中最明显的新增功能就是文件访问API的全面改进。多数开发者都用过java.io.File,对其存在的众多缺陷自然心中有数: ·不支持符号链接(symbolic links ) ·不支持简单移动和拷贝操作 ·目录漫游和过滤API非常复杂 ·对文件属性和访问权限的支持非常有限 ·没有查看目录或文件的API ·有限的错误处理功能 幸运的是,JSR 203不仅改进了以上所有缺点,而且实现了更多功能。这个API从一开始就设计为具备可扩展性,除了支持默认文件系统外,还支持嵌入式文件系统,还具有诸多灵活选项设置,可以实现诸如打开和拷贝文件、系统属性定义等操作。 Listing 2演示了JSR 203是如何被用来实现一些通用操作。Path是这个API的核心;你可以把它看作新建文件。 Listing 2 import java.nio.file.*; // FileSystems -> FileSystem -> Path FileSystem fileSystem = FileSystems.getDefault(); Path homeDir = fileSystem.getPath("/Users/lskywalker"); // Shortcut with Paths helper class Path homeDir = Paths.get("/Users/lskywalker"); Path secrets = homeDir.resolve("secrets.txt"); // Steal secrets secrets.moveTo(Paths.get("/Users/dvader/secrets.txt")); 除了文件系统API外,JSR 203还实现了许多在第一版NIO中提出的API,提供了对组播的更多支持,提供了在Socket和文件上进行异步I/O操作的API。 解决时间间隔问题 现有Java的Date和Calendar类一直都未能满足开发者的需要,一直都是开发者们的痛处。JSR 310:数据和时间API(Date and Time API)的目的就是提供一个完整的、功能齐备的Date和Time API。 JSR 310日期/时间API试图通过提供更好的性能和易用性改进Java的当前日期/时间API。例如,Java Calendar类将日期同时存储为与标准纪元之间的偏移量(以毫秒为单位)以及一组日历字段(例如,星期几、几号以及月份)。此双精度表示导致在意外的时间重新计算日历字段,从而产生不可预测的性能特点。与此相比,JSR 310类仅将日期/时间表示存储为与Date和Calendar所使用的同一标准纪元之间的偏移量(以毫秒为单位);仅当需要时才会计算日期等日历字段,并且不会使用这些日历字段进行内部日期表示。 JSR 310还对当前Java日期/时间模型进行了改进。Java 6 API不包含表示本地时间(不具有关联时区的时间)、持续时间或时间间隔的类。这迫使程序员使用令人困惑的设计做法,例如使用int表示持续时间。JSR 310包含表示上述各个概念的类,从而可以进行更为明确的程序设计。 最后,JSR 310 API通过使用不可改变的类努力实现线程安全。Java当前的日期/时间类Date和Calendar都是可改变的,因而都不是线程安全的。 更强的并行处理能力 JSR 166y是一个修订版JSR,它带给我们J2SE 5.0中所有java.util.concurrent的优点,以及Java SE 6中的全部更新。JSR 166y中的主要新增功能,是一个叫做fork/join的新并行处理包。尤其值得一提的是,fork/join提供了对分而治之算法的支持。fork /join库的核心是一个叫做ForkJoinPool的新类和实现问题分解的一系列任务类型。 多数典型应用一般不使用一个框架来解决计算密集型的分而治之算法。但是,JSR 166y还提供了一个新的功能式API,实现数组的并行处理。ParallelArray是一个可用于fork/join算法的数据结构,它提供了一个通用目的API,以高度并发的方式执行数据集的搜索、过滤和转换。其真正好处是,这些操作可以通过ForkJoinPool并行执行,在将来的多核计算时代,可以无需修改函数即可自动充分利用多核处理能力。至于ParalleArray是作为JDK的一部分包含在Java SE 7中,还是将作为一个外部库发布,现在尚处于考虑之中。 Listing 3演示了如何使用ParalleArray来管理donuts的大量集合。 Listing 3 // Instantiate the ForkJoinPool with a concurrency level ForkJoinPool fj = new ForkJoinPool(16); Donut[] data = ... ParallelArray donuts = new ParallelArray(fj, data); // Filter Ops.Predicate hasSprinkles = new Ops.Predicate() { public boolean op(Donut donut) { return donut.hasSprinkles(); } }; // Map from Donut -> Integer Ops.Predicate daysOld = new Ops.ObjectToInt() { public int op(Donut donut) { return donut.age(); } }; SummaryStatistics summary = orders.withFilter(hasSprinkles) .withMapping(daysOld) .summary(); System.out.println("with sprinkles: " + summary.size()); System.out.println("avg age: " + summary.average()); J2SE 5.0中引入的并行功能和其在Java SE 6中的改进,为我们在4核或8核服务器上编写并行应用程序提供了坚实的基础。而fork/join库则又向前更深入了一步,可以支持更多处理器的应用程序编写,诸如未来几年中我们将使用的16核到32核计算机。它缓解了我们所面临的并行计算问题,但并未真正解决它。现在业界中的每一个人都在寻找可以利用多核世界进行编程的方法。尽管Java在此方面有一定领先优势,但共享状态的并发编程不可能在未来十年中都满足所有需求。Fork/join只是进一步的尝试。 |