加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Five ways to maximize Java NIO and NIO.2--转

发布时间:2020-12-14 06:20:54 所属栏目:Java 来源:网络整理
导读:原文地址:http://www.javaworld.com/article/2078654/java-se/java-se-five-ways-to-maximize-java-nio-and-nio-2.html Java NIO -- the New Input/Output API package-- was introduced with J2SE 1.4 in 2002. Java NIO's purpose was to improve the pro

原文地址:http://www.javaworld.com/article/2078654/java-se/java-se-five-ways-to-maximize-java-nio-and-nio-2.html

Java NIO -- the New Input/Output API package-- was introduced with J2SE 1.4 in 2002. Java NIO's purpose was to improve the programming of I/O-intensive chores on the Java platform. A decade later,many Java programmers still don't know how to make the best use of NIO,and even fewer are aware that Java SE 7 introduced More New Input/Output APIs (NIO.2). In this tutorial you'll find five easy examples that demonstrate the advantages of the NIO and NIO.2 packages in common Java programming scenarios.

The primary contribution of NIO and NIO.2 to the Java platform is to improve performance in one of the core areas of Java application development: input/output processing. Neither package is particularly easy to work with,nor are the New Input/Output APIs required for every Java I/O scenario. Used correctly,though,Java NIO and NIO.2 can slash the time required for some common I/O operations. That's the superpower of NIO and NIO.2,and this article presents five relatively simple ways to leverage it:

The NIO context

How is it that a 10-year-old enhancement is still the?NewInput/Output package for Java? The reason is that for many working Java programmers the basic Java I/O operations are more than adequate. Most Java developers don't?have?to learn NIO for our daily work. Moreover,NIO isn't just a performance package. Instead,it's a heterogeneous collection of?facilities related to Java I/O. NIO boosts Java application performance by getting "closer to the metal" of a Java program,meaning that the NIO and NIO.2 APIs expose lower-level-system operating-system (OS) entry points. The tradeoff of NIO is that it simultaneously gives us greater control over I/O and demands that we exercise more care than we would with basic I/O programming. Another aspect of NIO is its attention to application expressivity,which we'll play with in some of the exercises that follow.

Plenty of good references are available for NIO -- see??for some selected links. For starting out with NIO and NIO.2,the??and??are indispensable. In order to run the examples in this article you will need to be working with??or greater.

For many developers the first encounter with NIO might happen during maintenance work: an application has correct functionality but is slow to respond,so someone suggests using NIO to accelerate it. NIO shines when it's used to boost processing performance,but its results will be closely tied to the underlying platform. (Note that NIO is platform dependent.) If you're using NIO for the first time,it will pay you to measure carefully. You might discover that NIO's ability to accelerate application performance depends not only on the OS,but on the specific JVM,host virtualization context,mass storage characteristics,and even data. Measurement can be tricky to generalize,however. Keep this in mind particularly if a mobile deployment is among your targets.

And now,without further ado,let's explore five important facilities of NIO and NIO.2.

1. Change notifiers (because everybody needs a listener)

Java application performance is the common draw for developers interested in NIO or NIO.2. In my experience,however,NIO.2's file change notifier is the most compelling (if under-sung) feature of the New Input/Output APIs.

Many enterprise-class applications need to take a specific action when:

  • A file is uploaded into an FTP folder
  • A configuration definition is changed
  • A draft document is updated
  • Another file-system event occurs

These are all examples of change notification or change response. In early versions of Java (and other languages),?polling?was typically the best way to detect change events. Polling is a particular kind of endless loop: check the file-system or other object,compare it to its last-known state,and,if there's no change,check back again after a brief interval,such as a hundred milliseconds or ten seconds. Continue the loop indefinitely.

NIO.2 gives us a better way to express change detection. Listing 1 is a simple example.

Listing 1. Change notification in NIO.2

<span class="kwd">public<span class="pln"> <span class="kwd">class<span class="pln"> <span class="typ">Watcher<span class="pln"> <span class="pun">{<span class="pln">
<span class="kwd">public<span class="pln"> <span class="kwd">static<span class="pln"> <span class="kwd">void<span class="pln"> main<span class="pun">(<span class="typ">String<span class="pun">[]<span class="pln"> args<span class="pun">)<span class="pln"> <span class="pun">{<span class="pln">
<span class="typ">Path<span class="pln"> this_dir <span class="pun">=<span class="pln"> <span class="typ">Paths<span class="pun">.<span class="kwd">get<span class="pun">(<span class="str">"."<span class="pun">);<span class="pln">
<span class="typ">System<span class="pun">.<span class="kwd">out<span class="pun">.<span class="pln">println<span class="pun">(<span class="str">"Now watching the current directory ..."<span class="pun">);<span class="pln">

      <span class="kwd"&gt;try<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
          <span class="typ"&gt;WatchService<span class="pln"&gt; watcher <span class="pun"&gt;=<span class="pln"&gt; this_dir<span class="pun"&gt;.<span class="pln"&gt;getFileSystem<span class="pun"&gt;().<span class="pln"&gt;newWatchService<span class="pun"&gt;();<span class="pln"&gt;
          this_dir<span class="pun"&gt;.<span class="kwd"&gt;register<span class="pun"&gt;(<span class="pln"&gt;watcher<span class="pun"&gt;,<span class="pln"&gt; <span class="typ"&gt;StandardWatchEventKinds<span class="pun"&gt;.<span class="pln"&gt;ENTRY_CREATE<span class="pun"&gt;);<span class="pln"&gt;

          <span class="typ"&gt;WatchKey<span class="pln"&gt; watckKey <span class="pun"&gt;=<span class="pln"&gt; watcher<span class="pun"&gt;.<span class="pln"&gt;take<span class="pun"&gt;();<span class="pln"&gt;

          <span class="typ"&gt;List<span class="pun"&gt;<<span class="typ"&gt;WatchEvent<span class="pun"&gt;<<span class="pln"&gt; <span class="pun"&gt;&amp;<span class="lit"&gt;64<span class="pun"&gt;;>><span class="pln"&gt; events <span class="pun"&gt;=<span class="pln"&gt; watckKey<span class="pun"&gt;.<span class="pln"&gt;pollEvents<span class="pun"&gt;();<span class="pln"&gt;
          <span class="kwd"&gt;for<span class="pln"&gt; <span class="pun"&gt;(<span class="typ"&gt;WatchEvent<span class="pln"&gt; <span class="kwd"&gt;event<span class="pln"&gt; <span class="pun"&gt;:<span class="pln"&gt; events<span class="pun"&gt;)<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
              <span class="typ"&gt;System<span class="pun"&gt;.<span class="kwd"&gt;out<span class="pun"&gt;.<span class="pln"&gt;println<span class="pun"&gt;(<span class="str"&gt;"Someone just created the file '"<span class="pln"&gt; <span class="pun"&gt;+<span class="pln"&gt; <span class="kwd"&gt;event<span class="pun"&gt;.<span class="pln"&gt;context<span class="pun"&gt;().<span class="pln"&gt;toString<span class="pun"&gt;()<span class="pln"&gt; <span class="pun"&gt;+<span class="pln"&gt; <span class="str"&gt;"'."<span class="pun"&gt;);<span class="pln"&gt;

         <span class="pun"&gt;}<span class="pln"&gt;

     <span class="pun"&gt;}<span class="pln"&gt; <span class="kwd"&gt;catch<span class="pln"&gt; <span class="pun"&gt;(<span class="typ"&gt;Exception<span class="pln"&gt; e<span class="pun"&gt;)<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
         <span class="typ"&gt;System<span class="pun"&gt;.<span class="kwd"&gt;out<span class="pun"&gt;.<span class="pln"&gt;println<span class="pun"&gt;(<span class="str"&gt;"Error: "<span class="pln"&gt; <span class="pun"&gt;+<span class="pln"&gt; e<span class="pun"&gt;.<span class="pln"&gt;toString<span class="pun"&gt;());<span class="pln"&gt;
     <span class="pun"&gt;}<span class="pln"&gt;
  <span class="pun"&gt;}<span class="pln"&gt;

<span class="pun">}

Compile this source,then launch the command-line executable. In the same directory,create a new file; you might,for example,?touch example1,or even?copy Watcher.class example1. You should see the following change notification message:

Someone just create the file 'example1'.

This simple example illustrates how to begin accessing NIO's language facilities in Java. It also introduces NIO.2'sWatcher?class,which is considerably more straightforward and easy-to-use for change notification than the traditional I/O solution based on polling.

Be careful when you copy source from this article. Note,for instance,that theStandardWatchEventKinds?object in Listing 1 is spelled as a plural. Even the?missed that!

Tip

NIO's notifiers are so much easier to use than the polling loops of old that it's tempting to neglect requirements analysis. But you should think through these semantics the first time you use a listener. Knowing when a file modification?ends?is more useful than knowing when it begins,for instance. That kind of analysis takes some care,especially in a common case like the FTP drop folder. NIO is a powerful package with some subtle "gotcha's"; it can punish a casual visitor.

2. Selectors and asynchronous I/O: Selectors help multiplex

Newcomers to NIO sometimes associate it with "non-blocking input/output." NIO is more than non-blocking I/O but the error makes sense: basic I/O in Java is?blocking?-- meaning that it waits until it can complete an operation -- whereas non-blocking,or asynchronous,I/O is one of the most-used NIO facilities.

NIO's non-blocking I/O is?event-based,as demonstrated by the file-system listener in Listing 1. This means that a?selector?(or callback or listener) is defined for an I/O channel,then processing continues. When an event occurs on the selector -- when a line of input arrives,for instance -- the selector "wakes up" and executes. All of this is achieved?within a single thread,which is a significant contrast to typical Java I/O.

Listing 2 demonstrates the use of NIO selectors in a multi-port networking echo-er,a program slightly modified from one created by Greg Travis in 2003 (see?). Unix and Unix-like operating systems have long had efficient implementations of selectors,so this sort of networking program is a model of good performance for a Java-coded networking program.

Listing 2. NIO selectors

<span class="kwd">public<span class="pln"> <span class="kwd">class<span class="pln"> <span class="typ">MultiPortEcho<span class="pln">
<span class="pun">{<span class="pln">
<span class="kwd">private<span class="pln"> <span class="kwd">int<span class="pln"> ports<span class="pun">[];<span class="pln">
<span class="kwd">private<span class="pln"> <span class="typ">ByteBuffer<span class="pln"> echoBuffer <span class="pun">=<span class="pln"> <span class="typ">ByteBuffer<span class="pun">.<span class="pln">allocate<span class="pun">(<span class="pln"> <span class="lit">1024<span class="pln"> <span class="pun">);<span class="pln">

<span class="kwd"&gt;public<span class="pln"&gt; <span class="typ"&gt;MultiPortEcho<span class="pun"&gt;(<span class="pln"&gt; <span class="kwd"&gt;int<span class="pln"&gt; ports<span class="pun"&gt;[]<span class="pln"&gt; <span class="pun"&gt;)<span class="pln"&gt; <span class="kwd"&gt;throws<span class="pln"&gt; <span class="typ"&gt;IOException<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
  <span class="kwd"&gt;this<span class="pun"&gt;.<span class="pln"&gt;ports <span class="pun"&gt;=<span class="pln"&gt; ports<span class="pun"&gt;;<span class="pln"&gt;

  configure_selector<span class="pun"&gt;();<span class="pln"&gt;
<span class="pun"&gt;}<span class="pln"&gt;

<span class="kwd"&gt;private<span class="pln"&gt; <span class="kwd"&gt;void<span class="pln"&gt; configure_selector<span class="pun"&gt;()<span class="pln"&gt; <span class="kwd"&gt;throws<span class="pln"&gt; <span class="typ"&gt;IOException<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
  <span class="com"&gt;// Create a new selector<span class="pln"&gt;
  <span class="typ"&gt;Selector<span class="pln"&gt; selector <span class="pun"&gt;=<span class="pln"&gt; <span class="typ"&gt;Selector<span class="pun"&gt;.<span class="pln"&gt;open<span class="pun"&gt;();<span class="pln"&gt;

  <span class="com"&gt;// Open a listener on each port,and register each one<span class="pln"&gt;
  <span class="com"&gt;// with the selector<span class="pln"&gt;
  <span class="kwd"&gt;for<span class="pln"&gt; <span class="pun"&gt;(<span class="kwd"&gt;int<span class="pln"&gt; i<span class="pun"&gt;=<span class="lit"&gt;0<span class="pun"&gt;;<span class="pln"&gt; i<span class="pun"&gt;<<span class="pln"&gt;ports<span class="pun"&gt;.<span class="pln"&gt;length<span class="pun"&gt;;<span class="pln"&gt; <span class="pun"&gt;++<span class="pln"&gt;i<span class="pun"&gt;)<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
    <span class="typ"&gt;ServerSocketChannel<span class="pln"&gt; ssc <span class="pun"&gt;=<span class="pln"&gt; <span class="typ"&gt;ServerSocketChannel<span class="pun"&gt;.<span class="pln"&gt;open<span class="pun"&gt;();<span class="pln"&gt;
    ssc<span class="pun"&gt;.<span class="pln"&gt;configureBlocking<span class="pun"&gt;(<span class="kwd"&gt;false<span class="pun"&gt;);<span class="pln"&gt;
    <span class="typ"&gt;ServerSocket<span class="pln"&gt; ss <span class="pun"&gt;=<span class="pln"&gt; ssc<span class="pun"&gt;.<span class="pln"&gt;socket<span class="pun"&gt;();<span class="pln"&gt;
    <span class="typ"&gt;InetSocketAddress<span class="pln"&gt; address <span class="pun"&gt;=<span class="pln"&gt; <span class="kwd"&gt;new<span class="pln"&gt; <span class="typ"&gt;InetSocketAddress<span class="pun"&gt;(<span class="pln"&gt;ports<span class="pun"&gt;[<span class="pln"&gt;i<span class="pun"&gt;]);<span class="pln"&gt;
    ss<span class="pun"&gt;.<span class="pln"&gt;bind<span class="pun"&gt;(<span class="pln"&gt;address<span class="pun"&gt;);<span class="pln"&gt;

    <span class="typ"&gt;SelectionKey<span class="pln"&gt; key <span class="pun"&gt;=<span class="pln"&gt; ssc<span class="pun"&gt;.<span class="kwd"&gt;register<span class="pun"&gt;(<span class="pln"&gt;selector<span class="pun"&gt;,<span class="pln"&gt; <span class="typ"&gt;SelectionKey<span class="pun"&gt;.<span class="pln"&gt;OP_ACCEPT<span class="pun"&gt;);<span class="pln"&gt;

    <span class="typ"&gt;System<span class="pun"&gt;.<span class="kwd"&gt;out<span class="pun"&gt;.<span class="pln"&gt;println<span class="pun"&gt;(<span class="str"&gt;"Going to listen on "<span class="pln"&gt; <span class="pun"&gt;+<span class="pln"&gt; ports<span class="pun"&gt;[<span class="pln"&gt;i<span class="pun"&gt;]);<span class="pln"&gt;
  <span class="pun"&gt;}<span class="pln"&gt;

  <span class="kwd"&gt;while<span class="pln"&gt; <span class="pun"&gt;(<span class="kwd"&gt;true<span class="pun"&gt;)<span class="pln"&gt; <span class="pun"&gt;{<span class="pln"&gt;
    <span class="kwd"&gt;int<span class="pln"&gt; num <span class="pun"&gt;=<span class="pln"&gt; selector<span class="pun"&gt;.<span class="kwd"&gt;select<span class="pun"&gt;();<span class="pln"&gt;

    <span class="typ"&gt;Set<span class="pln"&gt; selectedKeys <span class="pun"&gt;=<span class="pln"&gt; selector<span class="pun"&gt;.<span class="pln"&gt;selectedKeys<span class="pun"&gt;();<span class="pln"&gt;
    <span class="typ"&gt;Iterator<span class="pln"&gt; it <span class="pun"&gt;=<span class="pln"&gt; selectedKeys<span class="pun"&gt;.<span class="pln"&gt;iterator<span class="pun"&gt;();<span class="pln"&gt;

    <span class="kwd"&gt;while<span class="pln"&gt; <span class="pun"&gt;(<span class="pln"&gt;it<span class="pun"&gt;.<span class="pln"&gt;hasNext<span class="pun" class="pln"&gt;())<span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读