You are previewing Learning Java, 4th Edition.

Learning Java, 4th Edition

Cover of Learning Java, 4th Edition by Daniel Leuck... Published by O'Reilly Media, Inc.
  1. Learning Java
  2. Preface
    1. Who Should Read This Book
    2. New Developments
      1. New in This Edition (Java 6 and 7)
    3. Using This Book
    4. Online Resources
    5. Conventions Used in This Book
    6. Using Code Examples
    7. Safari® Books Online
    8. How to Contact Us
    9. Acknowledgments
  3. 1. A Modern Language
    1. Enter Java
      1. Java’s Origins
      2. Growing Up
    2. A Virtual Machine
    3. Java Compared with Other Languages
    4. Safety of Design
      1. Simplify, Simplify, Simplify...
      2. Type Safety and Method Binding
      3. Incremental Development
      4. Dynamic Memory Management
      5. Error Handling
      6. Threads
      7. Scalability
    5. Safety of Implementation
      1. The Verifier
      2. Class Loaders
      3. Security Managers
    6. Application and User-Level Security
    7. A Java Road Map
      1. The Past: Java 1.0–Java 1.6
      2. The Present: Java 7
      3. The Future
      4. Availability
  4. 2. A First Application
    1. Java Tools and Environment
    2. Configuring Eclipse and Creating a Project
      1. Importing the Learning Java Examples
    3. HelloJava
      1. Classes
      2. The main() Method
      3. Classes and Objects
      4. Variables and Class Types
      5. HelloComponent
      6. Inheritance
      7. The JComponent Class
      8. Relationships and Finger Pointing
      9. Package and Imports
      10. The paintComponent() Method
    4. HelloJava2: The Sequel
      1. Instance Variables
      2. Constructors
      3. Events
      4. The repaint() Method
      5. Interfaces
    5. HelloJava3: The Button Strikes!
      1. Method Overloading
      2. Components
      3. Containers
      4. Layout
      5. Subclassing and Subtypes
      6. More Events and Interfaces
      7. Color Commentary
      8. Static Members
      9. Arrays
      10. Our Color Methods
    6. HelloJava4: Netscape’s Revenge
      1. Threads
      2. The Thread Class
      3. The Runnable Interface
      4. Starting the Thread
      5. Running Code in the Thread
      6. Exceptions
      7. Synchronization
  5. 3. Tools of the Trade
    1. JDK Environment
    2. The Java VM
    3. Running Java Applications
      1. System Properties
    4. The Classpath
      1. javap
    5. The Java Compiler
    6. JAR Files
      1. File Compression
      2. The jar Utility
      3. The pack200 Utility
    7. Policy Files
      1. The Default Security Manager
      2. The policytool Utility
      3. Using a Policy File with the Default Security Manager
  6. 4. The Java Language
    1. Text Encoding
      1. Javadoc Comments
    3. Types
      1. Primitive Types
      2. Reference Types
      3. A Word About Strings
    4. Statements and Expressions
      1. Statements
      2. Expressions
    5. Exceptions
      1. Exceptions and Error Classes
      2. Exception Handling
      3. Bubbling Up
      4. Stack Traces
      5. Checked and Unchecked Exceptions
      6. Throwing Exceptions
      7. try Creep
      8. The finally Clause
      9. Try with Resources
      10. Performance Issues
    6. Assertions
      1. Enabling and Disabling Assertions
      2. Using Assertions
    7. Arrays
      1. Array Types
      2. Array Creation and Initialization
      3. Using Arrays
      4. Anonymous Arrays
      5. Multidimensional Arrays
      6. Inside Arrays
  7. 5. Objects in Java
    1. Classes
      1. Accessing Fields and Methods
      2. Static Members
    2. Methods
      1. Local Variables
      2. Shadowing
      3. Static Methods
      4. Initializing Local Variables
      5. Argument Passing and References
      6. Wrappers for Primitive Types
      7. Autoboxing and Unboxing of Primitives
      8. Variable-Length Argument Lists
      9. Method Overloading
    3. Object Creation
      1. Constructors
      2. Working with Overloaded Constructors
      3. Static and Nonstatic Initializer Blocks
    4. Object Destruction
      1. Garbage Collection
      2. Finalization
      3. Weak and Soft References
    5. Enumerations
      1. Enum Values
      2. Customizing Enumerations
  8. 6. Relationships Among Classes
    1. Subclassing and Inheritance
      1. Shadowed Variables
      2. Overriding Methods
      3. Special References: this and super
      4. Casting
      5. Using Superclass Constructors
      6. Full Disclosure: Constructors and Initialization
      7. Abstract Methods and Classes
    2. Interfaces
      1. Interfaces as Callbacks
      2. Interface Variables
      3. Subinterfaces
    3. Packages and Compilation Units
      1. Compilation Units
      2. Package Names
      3. Class Visibility
      4. Importing Classes
    4. Visibility of Variables and Methods
      1. Basic Access Modifiers
      2. Subclasses and Visibility
      3. Interfaces and Visibility
    5. Arrays and the Class Hierarchy
      1. ArrayStoreException
    6. Inner Classes
      1. Inner Classes as Adapters
      2. Inner Classes Within Methods
  9. 7. Working with Objects and Classes
    1. The Object Class
      1. Equality and Equivalence
      2. Hashcodes
      3. Cloning Objects
    2. The Class Class
    3. Reflection
      1. Modifiers and Security
      2. Accessing Fields
      3. Accessing Methods
      4. Accessing Constructors
      5. What About Arrays?
      6. Accessing Generic Type Information
      7. Accessing Annotation Data
      8. Dynamic Interface Adapters
      9. What Is Reflection Good For?
    4. Annotations
      1. Using Annotations
      2. Standard Annotations
      3. The apt Tool
  10. 8. Generics
    1. Containers: Building a Better Mousetrap
      1. Can Containers Be Fixed?
    2. Enter Generics
      1. Talking About Types
    3. “There Is No Spoon”
      1. Erasure
      2. Raw Types
    4. Parameterized Type Relationships
      1. Why Isn’t a List<Date> a List<Object>?
    5. Casts
    6. Writing Generic Classes
      1. The Type Variable
      2. Subclassing Generics
      3. Exceptions and Generics
      4. Parameter Type Limitations
    7. Bounds
      1. Erasure and Bounds (Working with Legacy Code)
    8. Wildcards
      1. A Supertype of All Instantiations
      2. Bounded Wildcards
      3. Thinking Outside the Container
      4. Lower Bounds
      5. Reading, Writing, and Arithmetic
      6. <?>, <Object>, and the Raw Type
      7. Wildcard Type Relationships
    9. Generic Methods
      1. Generic Methods Introduced
      2. Type Inference from Arguments
      3. Type Inference from Assignment Context
      4. Explicit Type Invocation
      5. Wildcard Capture
      6. Wildcard Types Versus Generic Methods
    10. Arrays of Parameterized Types
      1. Using Array Types
      2. What Good Are Arrays of Generic Types?
      3. Wildcards in Array Types
    11. Case Study: The Enum Class
    12. Case Study: The sort() Method
    13. Conclusion
  11. 9. Threads
    1. Introducing Threads
      1. The Thread Class and the Runnable Interface
      2. Controlling Threads
      3. Death of a Thread
    2. Threading an Applet
      1. Issues Lurking
    3. Synchronization
      1. Serializing Access to Methods
      2. Accessing class and instance Variables from Multiple Threads
      3. The wait() and notify() Methods
      4. Passing Messages
      5. ThreadLocal Objects
    4. Scheduling and Priority
      1. Thread State
      2. Time-Slicing
      3. Priorities
      4. Yielding
    5. Thread Groups
      1. Working with ThreadGroups
      2. Uncaught Exceptions
    6. Thread Performance
      1. The Cost of Synchronization
      2. Thread Resource Consumption
    7. Concurrency Utilities
      1. Executors
      2. Locks
      3. Synchronization Constructs
      4. Atomic Operations
    8. Conclusion
  12. 10. Working with Text
    1. Text-Related APIs
    2. Strings
      1. Constructing Strings
      2. Strings from Things
      3. Comparing Strings
      4. Searching
      5. Editing
      6. String Method Summary
      7. StringBuilder and StringBuffer
    3. Internationalization
      1. The java.util.Locale Class
      2. Resource Bundles
    4. Parsing and Formatting Text
      1. Parsing Primitive Numbers
      2. Tokenizing Text
    5. Printf-Style Formatting
      1. Formatter
      2. The Format String
      3. String Conversions
      4. Primitive and Numeric Conversions
      5. Flags
      6. Miscellaneous
    6. Formatting with the java.text Package
      1. MessageFormat
    7. Regular Expressions
      1. Regex Notation
      2. The java.util.regex API
  13. 11. Core Utilities
    1. Math Utilities
      1. The java.lang.Math Class
      2. Big/Precise Numbers
      3. Floating-Point Components
      4. Random Numbers
    2. Dates and Times
      1. Working with Calendars
      2. Time Zones
      3. Parsing and Formatting with DateFormat
      4. Printf-Style Date and Time Formatting
    3. Timers
    4. Collections
      1. The Collection Interface
      2. Iterator
      3. Collection Types
      4. The Map Interface
      5. Collection Implementations
      6. Hash Codes and Key Values
      7. Synchronized and Unsynchronized Collections
      8. Read-Only and Read-Mostly Collections
      9. WeakHashMap
      10. EnumSet and EnumMap
      11. Sorting Collections
      12. A Thrilling Example
    5. Properties
      1. Loading and Storing
      2. System Properties
    6. The Preferences API
      1. Preferences for Classes
      2. Preferences Storage
      3. Change Notification
    7. The Logging API
      1. Overview
      2. Logging Levels
      3. A Simple Example
      4. Logging Setup Properties
      5. The Logger
      6. Performance
    8. Observers and Observables
  14. 12. Input/Output Facilities
    1. Streams
      1. Basic I/O
      2. Character Streams
      3. Stream Wrappers
      4. Pipes
      5. Streams from Strings and Back
      6. Implementing a Filter Stream
    2. File I/O
      1. The Class
      2. File Streams
      3. RandomAccessFile
      4. Resource Paths
    3. The NIO File API
      1. FileSystem and Path
      2. NIO File Operations
      3. Directory Operations
      4. Watching Paths
    4. Serialization
      1. Initialization with readObject()
      2. SerialVersionUID
    5. Data Compression
      1. Archives and Compressed Data
      2. Decompressing Data
      3. Zip Archive As a Filesystem
    6. The NIO Package
      1. Asynchronous I/O
      2. Performance
      3. Mapped and Locked Files
      4. Channels
      5. Buffers
      6. Character Encoders and Decoders
      7. FileChannel
      8. Scalable I/O with NIO
  15. 13. Network Programming
    1. Sockets
      1. Clients and Servers
      2. author="pat” timestamp="20120926T110720-0500” comment="one of those sections I hate to get rid of but is less relevant in terms of the example... should probably find a more modern example...”The DateAtHost Client
      3. The TinyHttpd Server
      4. Socket Options
      5. Proxies and Firewalls
    2. Datagram Sockets
      1. author="pat” timestamp="20120926T141346-0500” comment="I actually rewrote this as a standalone client but then decided to leave it as an applet”The HeartBeat Applet
      2. InetAddress
    3. Simple Serialized Object Protocols
      1. A Simple Object-Based Server
    4. Remote Method Invocation
      1. Real-World Usage
      2. Remote and Nonremote Objects
      3. An RMI Example
      4. RMI and CORBA
    5. Scalable I/O with NIO
      1. Selectable Channels
      2. Using Select
      3. LargerHttpd
      4. Nonblocking Client-Side Operations
  16. 14. Programming for the Web
    1. Uniform Resource Locators (URLs)
    2. The URL Class
      1. Stream Data
      2. Getting the Content as an Object
      3. Managing Connections
      4. Handlers in Practice
      5. Useful Handler Frameworks
    3. Talking to Web Applications
      1. Using the GET Method
      2. Using the POST Method
      3. The HttpURLConnection
      4. SSL and Secure Web Communications
      5. URLs, URNs, and URIs
    4. Web Services
      1. XML-RPC
      2. WSDL
      3. The Tools
      4. The Weather Service Client
  17. 15. Web Applications and Web Services
    1. Web Application Technologies
      1. Page-Oriented Versus “Single Page” Applications
      2. JSPs
      3. XML and XSL
      4. Web Application Frameworks
      5. Google Web Toolkit
      6. HTML5, AJAX, and More...
    2. Java Web Applications
      1. The Servlet Lifecycle
      2. Servlets
      3. The HelloClient Servlet
      4. The Servlet Response
      5. Servlet Parameters
      6. The ShowParameters Servlet
      7. User Session Management
      8. The ShowSession Servlet
      9. The ShoppingCart Servlet
      10. Cookies
      11. The ServletContext API
      12. Asynchronous Servlets
    3. WAR Files and Deployment
      1. Configuration with web.xml and Annotations
      2. URL Pattern Mappings
      3. Deploying HelloClient
      4. Error and Index Pages
      5. Security and Authentication
      6. Protecting Resources with Roles
      7. Secure Data Transport
      8. Authenticating Users
      9. Procedural Authorization
    4. Servlet Filters
      1. A Simple Filter
      2. A Test Servlet
      3. Declaring and Mapping Filters
      4. Filtering the Servlet Request
      5. Filtering the Servlet Response
    5. Building WAR Files with Ant
      1. A Development-Oriented Directory Layout
      2. Deploying and Redeploying WARs with Ant
    6. Implementing Web Services
      1. Defining the Service
      2. Our Echo Service
      3. Using the Service
      4. Data Types
    7. Conclusion
  18. 16. Swing
    1. Components
      1. Peers and Look-and-Feel
      2. The MVC Framework
      3. Painting
      4. Enabling and Disabling Components
      5. Focus, Please
      6. Other Component Methods
      7. Layout Managers
      8. Insets
      9. Z-Ordering (Stacking Components)
      10. The revalidate() and doLayout() Methods
      11. Managing Components
      12. Listening for Components
      13. Windows, Frames and Splash Screens
      14. Other Methods for Controlling Frames
      15. Content Panes
      16. Desktop Integration
    2. Events
      1. Event Receivers and Listener Interfaces
      2. Event Sources
      3. Event Delivery
      4. Event Types
      5. The java.awt.event.InputEvent Class
      6. Mouse and Key Modifiers on InputEvents
      7. Focus Events
    3. Event Summary
      1. Adapter Classes
      2. Dummy Adapters
    4. The AWT Robot!
    5. Multithreading in Swing
  19. 17. Using Swing Components
    1. Buttons and Labels
      1. HTML Text in Buttons and Labels
    2. Checkboxes and Radio Buttons
    3. Lists and Combo Boxes
    4. The Spinner
    5. Borders
    6. Menus
    7. Pop-Up Menus
      1. Component-Managed Pop Ups
    8. The JScrollPane Class
    9. The JSplitPane Class
    10. The JTabbedPane Class
    11. Scrollbars and Sliders
    12. Dialogs
      1. File Selection Dialog
      2. The Color Chooser
  20. 18. More Swing Components
    1. Text Components
      1. The TextEntryBox Application
      2. Formatted Text
      3. Filtering Input
      4. Validating Data
      5. Say the Magic Word
      6. Sharing a Data Model
      7. HTML and RTF for Free
      8. Managing Text Yourself
    2. Focus Navigation
      1. Trees
      2. Nodes and Models
      3. Save a Tree
      4. Tree Events
      5. A Complete Example
    3. Tables
      1. A First Stab: Freeloading
      2. Round Two: Creating a Table Model
      3. Round Three: A Simple Spreadsheet
      4. Sorting and Filtering
      5. Printing JTables
    4. Desktops
    5. Pluggable Look-and-Feel
    6. Creating Custom Components
      1. Generating Events
      2. A Dial Component
      3. Model and View Separation
  21. 19. Layout Managers
    1. FlowLayout
    2. GridLayout
    3. BorderLayout
    4. BoxLayout
    5. CardLayout
    6. GridBagLayout
      1. The GridBagConstraints Class
      2. Grid Coordinates
      3. The fill Constraint
      4. Spanning Rows and Columns
      5. Weighting
      6. Anchoring
      7. Padding and Insets
      8. Relative Positioning
      9. Composite Layouts
    7. Other Layout Managers
    8. Absolute Positioning
  22. 20. Drawing with the 2D API
    1. The Big Picture
    2. The Rendering Pipeline
    3. A Quick Tour of Java 2D
      1. Filling Shapes
      2. Drawing Shape Outlines
      3. Convenience Methods
      4. Drawing Text
      5. Drawing Images
      6. The Whole Iguana
    4. Filling Shapes
      1. Solid Colors
      2. Color Gradients
      3. Textures
      4. Desktop Colors
    5. Stroking Shape Outlines
    6. Using Fonts
      1. Font Metrics
    7. Displaying Images
      1. The Image Class
      2. Image Observers
      3. Scaling and Size
    8. Drawing Techniques
      1. Double Buffering
      2. Limiting Drawing with Clipping
      3. Offscreen Drawing
    9. Printing
  23. 21. Working with Images and Other Media
    1. Loading Images
      1. ImageObserver
      2. MediaTracker
      3. ImageIcon
      4. ImageIO
    2. Producing Image Data
      1. Drawing Animations
      2. BufferedImage Anatomy
      3. Color Models
      4. Creating an Image
      5. Updating a BufferedImage
    3. Filtering Image Data
      1. How ImageProcessor Works
      2. Converting an Image to a BufferedImage
      3. Using the RescaleOp Class
      4. Using the AffineTransformOp Class
    4. Saving Image Data
    5. Simple Audio
    6. Java Media Framework
  24. 22. JavaBeans
    1. What’s a Bean?
      1. What Constitutes a Bean?
    2. The NetBeans IDE
      1. Installing and Running NetBeans
    3. Properties and Customizers
    4. Event Hookups and Adapters
      1. Taming the Juggler
      2. Molecular Motion
    5. Binding Properties
      1. Constraining Properties
    6. Building Beans
      1. The Dial Bean
      2. Design Patterns for Properties
    7. Limitations of Visual Design
    8. Serialization Versus Code Generation
    9. Customizing with BeanInfo
      1. Getting Properties Information
    10. Handcoding with Beans
      1. Bean Instantiation and Type Management
      2. Working with Serialized Beans
      3. Runtime Event Hookups with Reflection
    11. BeanContext and BeanContextServices
    12. The Java Activation Framework
    13. Enterprise JavaBeans and POJO-Based Enterprise Frameworks
  25. 23. Applets
    1. The Politics of Browser-Based Applications
    2. Applet Support and the Java Plug-in
    3. The JApplet Class
      1. Applet Lifecycle
      2. The Applet Security Sandbox
      3. Getting Applet Resources
      4. The <applet> Tag
      5. Attributes
      6. Parameters
      7. ¿Habla Applet?
      8. The Complete <applet> Tag
      9. Loading Class Files
      10. Packages
      11. appletviewer
    4. Java Web Start
    5. Conclusion
  26. 24. XML
    1. The Butler Did It
    2. A Bit of Background
      1. Text Versus Binary
      2. A Universal Parser
      3. The State of XML
      4. The XML APIs
      5. XML and Web Browsers
    3. XML Basics
      1. Attributes
      2. XML Documents
      3. Encoding
      4. Namespaces
      5. Validation
      6. HTML to XHTML
    4. SAX
      1. The SAX API
      2. Building a Model Using SAX
      3. XMLEncoder/Decoder
    5. DOM
      1. The DOM API
      2. Test-Driving DOM
      3. Generating XML with DOM
      4. JDOM
    6. XPath
      1. Nodes
      2. Predicates
      3. Functions
      4. The XPath API
      5. XMLGrep
    7. XInclude
      1. Enabling XInclude
    8. Validating Documents
      1. Using Document Validation
      2. DTDs
      3. XML Schema
      4. The Validation API
    9. JAXB Code Binding and Generation
      1. Annotating Our Model
      2. Generating a Java Model from an XML Schema
      3. Generating an XML Schema from a Java Model
    10. Transforming Documents with XSL/XSLT
      1. XSL Basics
      2. Transforming the Zoo Inventory
      3. XSLTransform
      4. XSL in the Browser
    11. Web Services
    12. The End of the Book
  27. A. The Eclipse IDE
    1. The IDE Wars
    2. Getting Started with Eclipse
      1. Importing the Learning Java Examples
    3. Using Eclipse
      1. Getting at the Source
      2. The Lay of the Land
      3. Running the Examples
      4. Building the Ant-Based Examples
      5. Loner Examples
    4. Eclipse Features
      1. Coding Shortcuts
      2. Autocorrection
      3. Refactoring
      4. Diffing Files
      5. Organizing Imports
      6. Formatting Source Code
    5. Conclusion
  28. B. BeanShell: Java Scripting
    1. Running BeanShell
    2. Java Statements and Expressions
      1. Imports
    3. BeanShell Commands
    4. Scripted Methods and Objects
      1. Scripting Interfaces and Adapters
    5. Changing the Classpath
    6. Learning More . . .
  29. Glossary
  30. Index
  31. About the Authors
  32. Colophon
  33. Copyright
O'Reilly logo

Scalable I/O with NIO

We’ll now conclude the discussion of the NIO package we began in Chapter 12 by talking about nonblocking and selectable network communications. All our server examples in this chapter thus far have used a thread-bound pattern (one thread per I/O operation). In Java, this is very natural because of the ease with which we can create threads. It’s also very efficient, within limits. Problems arise when you try to build very large-scale servers using this style of client handling. While on a large machine it’s certainly possible to have hundreds or even thousands of threads (especially if they’re mostly idle, waiting for I/O), this is a resource-hungry solution. Every thread you start in Java consumes memory for its internal stack, and the performance of managing this number of threads is highly system-dependent.

An alternate approach is to take a lesson from the old, dark days before threading was available and use nonblocking I/O operations to manage numerous communications from a single thread. Better yet, our server uses a configurable pool of threads, taking advantage of machines with many processors.

At the heart of this process is the concept of selectable I/O. It’s not good enough to simply have nonblocking I/O operations if you have no way to efficiently poll for work to be done. The NIO package provides for efficient polling using selectable channels. A selectable channel allows for the registration of a special kind of listener called a selector that can check the readiness of the channel for operations, such as reading and writing or accepting or creating network connections.

The selector and the selection process are not typical Java listeners of the kind we’ll see elsewhere in this book, but instead rather slavishly follow the conventions of C language systems. This is mainly for performance reasons; because this API is primarily intended for high-volume servers, it is bound very tightly to the traditional, underlying operating system facilities with less regard for ease of use. This, combined with the other details of using the NIO package, mean that this section is somewhat dense and the server we create here is one of the longer and more complex examples in the book. Don’t be discouraged if you are a bit put off by this section. You can use the general techniques earlier in this chapter for most applications and reserve this knowledge for creating services that handle the very highest volumes of simultaneous client requests.

Selectable Channels

A selectable channel implements the SelectableChannel interface, which specifies that the channel can be set to a nonblocking mode and that it supports the select API that makes efficient polling possible. The primary implementations of selectable channels are those for working with the network: SocketChannel, ServerSocketChannel, and DatagramChannel. The only other selectable channel is the Pipe (which can be used in an analogous way for intra-VM communication).

At the heart of the process is the Selector object, which knows about a particular set of selectable channels and provides a select() method for determining their readiness for I/O operations. Conceptually, the process is simple; you register one or more channels with a selector and then poll it, asking it to tell you which set of channels is ready to go. In actuality, there are a few additional pieces involved.

First, the Selector does not work directly with channels but instead operates on SelectionKey objects. A SelectionKey object is created implicitly when the channel is registered with the Selector. It encapsulates the selectable channel as well as information about what types of operations (e.g., read, write) we are interested in waiting for. That information is held in the SelectionKey in a set of flags called the interest set, which can be changed by the application at any time. SelectionKeys are also used to return the results of a select operation. Each call to select() returns the number of SelectionKeys that are ready for some type of I/O. The keys are then retrieved with the selectedKeys() method. Each key also has a set of flags called the ready set that indicates which operation of interest is actually ready (possibly more than one). For example, a SelectionKey interest set might indicate that we want to know when its channel is ready for reading or writing. After a select operation, if that key is in the set returned by the selector, we know that it is ready for one or more of those operations, and we can check the key’s ready set to find out which one.

Before we go on, we should say that although we have been saying that channels are registered with selectors, the API is (confusingly) the other way around. Selectors are actually registered with the one or more channels they manage, but it’s better to mentally spackle over this and think of them the other way around.

Using Select

A Selector object is created using the method (Selector uses a factory pattern):

    Selector selector =;

To register one or more channels with the selector, set them to nonblocking mode:

    SelectableChannel channelA = // ...
    channelA.configureBlocking( false );

Next, register the channels:

    int interestOps = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
    SelectionKey key = channelA.register( selector, interestOps );

When we register the channel, we have an opportunity to set the initial interest operations (or “interest ops”). These are defined by constant fields in the SelectionKey class:


Ready to read


Ready to write


Client-socket connection ready


Server-socket connection ready

These fields are bit flags; you can logically OR them together as in this example to express interest in more than one type of operation.

The result of the register() method is a SelectionKey object. We can use the key to change the interest ops at any time with the SelectionKey interestOps() method or to unregister the channel from the Selector with the key’s cancel() method.

This same key is also returned as the result of selection operations when its channel is ready. When the SelectionKey is returned, its ready set holds flags for the operations that do not block if called. We can retrieve the value of the flags with the readySet() method. Convenience methods are available to test for each operation in the ready set: isReadable(), isWritable(), isConnectable(), and isAcceptable().

Depending on how you structure your application, it may not be necessary to save the SelectionKey at registration time. In our example, we let the Selector keep track of the keys for us, simply using them when they are ready. In fact, we go even further and put the SelectionKey to work by asking it to hold a reference for us! The SelectionKey attach() method is a convenience method that can attach an arbitrary object to the key for use by our application. We show how this can be useful in a bit.

After one or more channels are registered with the Selector, we can perform a select operation using one of its select() methods:

    int readyCount =;

Without arguments, the method blocks until at least one channel is ready for some operation or until the Selector’s wakeup() method is called. Alternatively, you can use the form of select() that takes a timeout (in milliseconds) to wait for a ready channel before returning. There is also selectNow(), which always returns immediately. Both of these return methods count the number of ready channels.

You can use select() and wakeup() somewhat like wait() and notify(). The wakeup is necessary because once a selection is started, it will not see any changes to its key’s interest ops until the next invocation. If another thread changes the interest ops, it must use wakeup() to prompt the selecting thread to select() again. The Selector is also heavily synchronized; for example, calls to register new channels block until the select is finished. Often it’s much easier to simply use select with a short timeout and a loop, like this:

    while ( 50 ) == 0 );

However, if another thread is allowed to change the interest ops, you still need to use wakeup() to maximize throughput. Otherwise, in the worst case, you could end up waiting the full select wait period on every iteration, even when there is work to be done.

Next, we can get the set of ready channels from the Selector with the selectedKeys() method and iterate through them, doing whatever our application dictates:

    Set readySet = selector.selectedKeys();
    for( Iterator it = readySet.iterator(); it.hasNext(); ) {
        SelectionKey key = (SelectionKey);
        it.remove();  // remove the key from the ready set
     // use the key

The ready set is returned to us as a java.util.Set, which we walk through with an Iterator (see Chapter 1). One important thing to note is that we’ve used the Iterator’s remove() method to remove the key from the ready set. The select() methods add keys only to the ready set or add flags to keys already in the set; they never remove them, so we must clear the keys when we handle them. You can get the full set of keys a Selector is managing with the keys() method, but you should not attempt to remove keys from that set; use the cancel() method on individual keys instead. Or you can close the entire Selector with its close() method, unregistering all its keys.


Let’s put this information to use. In this section, we’ll create the big brother of TinyHttpd (our minimalist web server) called LargerHttpd. The LargerHttpd server is a nonblocking web server that uses SocketChannels and a pool of threads to service requests. In this example, a single thread executes a main loop that accepts new connections and checks the readiness of existing client connections for reading or writing. Whenever a client needs attention, it places the job in a queue where a thread from our thread pool waits to service it. As we said, this example is a bit longer than we would like, but it is really the minimum that is necessary to show a realistic usage of the APIs:

import java.util.*;
import java.util.concurrent.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.regex.*;

public class LargerHttpd
    Selector clientSelector;

    public void run( int port, int threads ) throws IOException 
        clientSelector =;
        ServerSocketChannel ssc =;
        InetSocketAddress sa =  new InetSocketAddress( InetAddress
            .getLoopbackAddress(), port );
        ssc.socket().bind( sa );
        ssc.register( clientSelector, SelectionKey.OP_ACCEPT );
        Executor executor = Executors.newFixedThreadPool( threads );

        while ( true ) {
            try {
                while ( == 0 );
                Set<SelectionKey> readySet = clientSelector.selectedKeys();
                for(Iterator<SelectionKey> it=readySet.iterator();
                    final SelectionKey key =;
                    if ( key.isAcceptable() ) {
                        acceptClient( ssc );
                    } else {
                        key.interestOps( 0 );
                        executor.execute( new Runnable() {
                          public void run() {
                            try {
                                handleClient( key );
                              } catch ( IOException e) {
                        } );
            } catch ( IOException e ) { System.out.println(e); }

    void acceptClient( ServerSocketChannel ssc ) throws IOException
        SocketChannel clientSocket = ssc.accept();
        clientSocket.configureBlocking(false);        SelectionKey key =  clientSocket.register( clientSelector,
            SelectionKey.OP_READ );
        HttpdConnection client = new HttpdConnection( clientSocket );
        key.attach( client );

    void handleClient( SelectionKey key ) throws IOException
        HttpdConnection client = (HttpdConnection)key.attachment();
        if ( key.isReadable() ) {
   key );
        } else {
            client.write( key );

    public static void main( String argv[] ) throws IOException {
        //new LargerHttpd().run( Integer.parseInt(argv[0]), 3/*threads*/ );
        new LargerHttpd().run( 1235, 3/*threads*/ );

class HttpdConnection 
    static Charset charset = Charset.forName("8859_1");
    static Pattern httpGetPattern = Pattern.compile("(?s)GET /?(\\S*).*");
    SocketChannel clientSocket;
    ByteBuffer buff = ByteBuffer.allocateDirect( 64*1024 );
    String request;
    String response;
    FileChannel file;
    int filePosition;

    HttpdConnection ( SocketChannel clientSocket ) {
        this.clientSocket = clientSocket;

    void read( SelectionKey key ) throws IOException {
        if ( request == null && ( buff ) == -1 
                || buff.get( buff.position()-1 ) == '\n' ) )
            processRequest( key );
            key.interestOps( SelectionKey.OP_READ );

    void processRequest( SelectionKey key ) {
        request = charset.decode( buff ).toString();
        Matcher get = httpGetPattern.matcher( request );
        if ( get.matches() ) {
            request =;
            if ( request.endsWith("/") || request.equals("") )
                request = request + "index.html";
            System.out.println( "Request: "+request);
            try {
                file = new FileInputStream ( request ).getChannel();
            } catch ( FileNotFoundException e ) {
                response = "404 Object Not Found";
        } else
            response = "400 Bad Request" ;

        if ( response != null ) {
                CharBuffer.wrap( response ), buff, true );
        key.interestOps( SelectionKey.OP_WRITE );

    void write( SelectionKey key ) throws IOException {
        if ( response != null ) {
            clientSocket.write( buff );
            if ( buff.remaining() == 0 ) 
                response = null;
        } else if ( file != null ) {
            int remaining = (int)file.size()-filePosition;
            long sent = file.transferTo( filePosition, remaining,
            if ( sent >= remaining || remaining <= 0 ) {
                file = null;
            } else
                filePosition += sent;
        if ( response == null && file == null ) {
        } else 
            key.interestOps( SelectionKey.OP_WRITE );

From a bird’s-eye view, the structure of LargerHttpd is the same as TinyHttpd. The main class, LargerHttpd, accepts connections, and a connection class, HttpdConnection, encapsulates a socket and handles the conversation with the client. However, this time, instead of each connection object being a Runnable serviced in its own thread, its functionality is broken into two primary methods called read() and write(). The job of our LargerHttpd is to accept new client socket connections, wrap them in an instance of HttpdConnection, and then watch the client’s status with a Selector. Whenever we detect that a client is ready to send or receive data, we hand off a Runnable task to our Executor. The task calls read() or write() on the corresponding client, based on the operation that is is ready.

The HttpConnection object encapsulates the state of the conversation with the client. Because its interface is rather coarse, it must keep track of whether it is waiting to read more input, generate a response, or write file output. The HttpdConnection also manages the interest set of its key so that it can effectively schedule itself to be woken up when it’s ready for reading or writing. The association between the HttpdConnection and the key is made by using the key’s attach() and attachment() methods.

LargerHttpd’s acceptClient() method does several things. First, it accepts the new socket connection. Next, it configures and registers it with the selector with an initial interest set for reading. Finally, it creates the HttpdConnection for the socket, and attaches the HttpdConnection object to the key for later retrieval.

The main loop of LargerHttpd is fairly straightforward. First, we set up the ServerSocketChannel. This is similar to setting up a plain ServerSocket, except that we must first create an InetSocketAddress object to hold the local loopback address and port combination of our server socket and then explicitly bind our socket to that address with the ServerSocketChannel bind() method. We also configure the server socket to nonblocking mode and register it with our main Selector so that we can select for client connections in the same loop that we use to select for client read and write readiness.

In the main select loop, we check to see whether the key is ready for an accept operation and if so, we call acceptClient(); if not, we set the key’s interest set to zero with the interestOps() method and dispatch the key to our handleClient() method via a Runnable task. It’s important that we change the interest set to zero to clear it before the next loop; otherwise, we’d be in a race to see whether the thread pool performed its maximum work before we detected another ready condition. Setting the interest ops to 0 and resetting it in the HttpdConnection object upon completion ensures that only one thread is handling a given client at a time.

For each operation that is ready, we dispatch a task to our Executor. The task calls handleClient(), passing it the selection key. From the key, we retrieve the associated HttpdConnection object and call the appropriate service method based on whether the key is ready for reading or writing. After that, it’s up to the connection object to do its job. Each call to the read() method simply does what would be one iteration of a read loop in a thread-bound application. Each read gets as much data as available and checks to see whether we’ve reached the end of a line (a \n newline character). Upon reaching the end of a line, we dispatch the call to the processRequest() method, which turns the byte buffer into text and uses the same techniques as our TinyHttpd to parse the request into a file pathname. On each incomplete call to read(), we set the interest ops of our key back to OP_READ. Upon completing the read and processing the request, we switch to using OP_WRITE because we are now ready to send a response.

The write() method keeps track of whether it’s sending a text response (error message) or a file by using the response and file instance variables. When sending a file, we use the FileChannel’s transferTo() method to transfer bytes from the file directly to the network socket without copying them into Java’s memory space. (This is indeed an efficient little web server.) And that’s about it. When we’re done, we close the client socket and cancel our key, which causes it to be removed from the Selector’s key set during the next select operation (discarding our HttpdConnection object with it).

Nonblocking Client-Side Operations

Our example showed SocketChannel used for nonblocking, selectable I/O in a typical server application. It’s less common to need nonblocking I/O from a client, but there is certainly no reason you can’t do it. Perhaps you’re writing a peer-to-peer (P2P) application that manages many connections from both sides.

For the client side of communications, one additional tool is provided: a nonblocking socket-connect operation. The process of creating a TCP connection from the client side involves contacting the remote host in a two-phase acknowledgment. This process normally blocks until the connection is established. However, the NIO package provides an alternative that allows you to initiate the connection and then poll for its status. When set to nonblocking mode, a call to a SocketChannel’s connect() method returns immediately. The connection is then attempted (and possibly succeeds or fails) in the background. Later, a Selector can be used, checking for the OP_CONNECT flag to see when the socket is ready to “finish connecting.” The connection is finished by invoking the SocketChannel’s finishConnect() method, which either returns or throws an IOException indicating the failure. The process of finishing the connection is really more about collecting the results of the asynchronous connection—acknowledging its success or failure—than about doing work.

The best content for your career. Discover unlimited learning on demand for around $1/day.