logo资料库

Concurrent Programming in Java.pdf

第1页 / 共317页
第2页 / 共317页
第3页 / 共317页
第4页 / 共317页
第5页 / 共317页
第6页 / 共317页
第7页 / 共317页
第8页 / 共317页
资料共317页,剩余部分请下载后查看
Concurrent Programming in Java™: Design Principles and Patterns, Second Edition
Copyright
Library of Congress Card Number 99-066823
Acknowledgments
Chapter 1. Concurrent Object-Oriented Programming
1.1 Using Concurrency Constructs
1.1.1 A Particle Applet
1.1.1.1 Particle
1.1.1.2 ParticleCanvas
1.1.1.3 ParticleApplet
1.1.2 Thread Mechanics
1.1.2.1 Construction
1.1.2.2 Starting threads
1.1.2.3 Priorities
1.1.2.4 Control methods
1.1.2.6 ThreadGroups
1.1.3 Further Readings
1.2 Objects and Concurrency
1.2.1 Concurrency
1.2.2 Concurrent Execution Constructs
1.2.2.1 Computer systems
1.2.2.2 Processes
1.2.2.3 Threads
1.2.2.4 Tasks and lightweight executable frameworks
1.2.3 Concurrency and OO Programming
1.2.3.1 Sequential OO programming
1.2.3.2 Event-based programming
1.2.3.3 Concurrent systems programming
1.2.3.4 Other concurrent programming languages
1.2.4 Object Models and Mappings
1.2.4.1 Object models
1.2.4.2 Sequential mappings
1.2.4.3 Active objects
1.2.4.4 Mixed models
1.2.5 Further Readings
1.2.5.1 Concurrent programming
1.2.5.2 Models
1.2.5.3 Distributed systems
1.2.5.4 Real-time programming
1.3 Design Forces
1.3.1 Safety
1.3.1.1 Attributes and constraints
1.3.1.2 Representational constraints
1.3.2 Liveness
1.3.3 Performance
1.3.4 Reusability
1.3.4.1 Closed subsystems
1.3.4.2 Open systems
1.3.4.3 Documentation
1.3.5 Further Readings
1.4 Before/After Patterns
1.4.1 Layering
1.4.2 Adapters
1.4.3 Subclassing
1.4.3.1 Template methods
1.4.4 Method Adapters
1.4.5 Further Readings
Chapter 2. Exclusion
2.1 Immutability
2.1.1 Applications
2.1.1.1 Abstract Data Types (ADTs)
2.1.1.2 Value containers
2.1.1.3 Sharing
2.1.2 Construction
2.2 Synchronization
2.2.1 Mechanics
2.2.1.1 Objects and locks
2.2.1.2 Synchronized methods and blocks
2.2.1.3 Acquiring and releasing locks
2.2.1.4 Statics
2.2.2 Fully Synchronized Objects
2.2.3 Traversal
2.2.3.1 Synchronized aggregate operations
2.2.3.2 Indexed traversal and client-side locking
2.2.3.3 Versioned iterators
2.2.3.4 Visitors
2.2.4 Statics and Singletons
2.2.5 Deadlock
2.2.6 Resource Ordering
2.2.7 The Java Memory Model
2.2.7.1 Atomicity
2.2.7.2 Visibility
2.2.7.3 Ordering
2.2.7.4 Volatile
2.2.8 Further Readings
2.3 Confinement
2.3.1 Confinement Across Methods
2.3.1.1 Sessions
2.3.1.2 Alternative protocols
2.3.2 Confinement Within Threads
2.3.2.1 Thread-specific fields
2.3.2.2 ThreadLocal
2.3.2.3 Applications and consequences
2.3.3 Confinement Within Objects
2.3.3.1 Adapters
2.3.3.2 Subclassing
2.3.4 Confinement Within Groups
2.3.4.1 Rings
2.3.5 Further Readings
2.4 Structuring and Refactoring Classes
2.4.1 Reducing Synchronization
2.4.1.1 Accessors
2.4.1.2 Double-check
2.4.1.3 Open calls
2.4.2 Splitting Synchronization
2.4.2.1 Splitting classes
2.4.2.2 Splitting locks
2.4.2.3 Isolating fields
2.4.2.4 Linked data structures
2.4.3. Read-Only Adapters
2.4.4 Copy-on-Write
2.4.4.1 Internal copy-on-write
2.4.4.2 Optimistic Updates
2.4.4.3 Atomic commitment
2.4.5 Open Containers
2.4.5.1 Internal disciplines
2.4.5.2 External disciplines
2.4.5.3 Multilevel containment
2.4.6 Further Readings
2.5 Using Lock Utilities
2.5.1 Mutexes
2.5.1.1 Method adapters
2.5.1.2 Back-offs
2.5.1.3 Reorderings
2.5.1.4 Non-block-structured locking
2.5.1.5 Lock Ordering Managers
2.5.2 Read-Write Locks
2.5.3 Further Readings
Chapter 3. State Dependence
3.1 Dealing with Failure
3.1.1 Exceptions
3.1.1.1 Abrupt termination
3.1.1.2 Continuation
3.1.1.3 Rollback
3.1.1.4 Roll-forward
3.1.1.5 Retry
3.1.1.6 Handlers
3.1.2 Cancellation
3.1.2.1 Interruption
3.1.2.2 IO and resource revocation
3.1.2.3 Asynchronous termination
3.1.2.4 Resource control
3.1.2.5 Multiphase cancellation
3.1.3 Further Readings
3.2 Guarded Methods
3.2.1 Guarded Suspension
3.2.1.1 Guards
3.2.1.2 State-based message acceptance
3.2.1.3 Defining logical control state
3.2.2 Monitor Mechanics
3.2.3 Guarded Waits
3.2.3.1 Interrupted waits
3.2.4 Notifications
3.2.4.1 Slipped conditions and missed signals
3.2.4.2 Single notifications
3.2.5 Timed Waits
3.2.6 Busy Waits
3.2.6.1 Efficiency
3.2.6.2 Scheduling
3.2.6.3 Triggering
3.2.6.4 Synchronizing actions
3.2.6.5 Implementations
3.3 Structuring and Refactoring Classes
3.3.1 Tracking State
3.3.1.1 Channels and bounded buffers
3.3.1.2 State variables
3.3.2 Conflict Sets
3.3.2.1 Implementation
3.3.2.2 Variants and extensions
3.3.3 Subclassing
3.3.3.1 Readers and Writers
3.3.3.2 Layering Guards
3.3.3.3 Inheritance anomalies
3.3.4 Confinement and Nested Monitors
3.3.5 Further Readings
3.4 Using Concurrency Control Utilities
3.4.1 Semaphores
3.4.1.1 Mutual exclusion locks
3.4.1.2 Resource pools
3.4.1.3 Bounded buffers
3.4.1.4 Synchronous channels
3.4.1.5 Fairness and scheduling
3.4.1.6 Priorities
3.4.2 Latches
3.4.2.1 Latching variables and predicates
3.4.3 Exchangers
3.4.4 Condition Variables
3.4.5 Further Readings
3.5 Joint Actions
3.5.1 General Solutions
3.5.1.1 Structure
3.5.1.2 Classes and methods
3.5.1.3 Liveness
3.5.1.4 Example
3.5.2 Decoupling Observers
3.5.3 Further Readings
3.6 Transactions
3.6.1 Transaction Protocols
3.6.2 Transaction Participants
3.6.2.1 Interfaces
3.6.2.2 Implementations
3.6.3 Creating Transactions
3.6.3.1 Example
3.6.4 Vetoable Changes
3.6.5 Further Readings
3.7 Implementing Utilities
3.7.1 Acquire-Release Protocols
3.7.2 Delegated Actions
3.7.2.1 Design steps
3.7.2.2 Bounded buffers
3.7.2.3 Collapsing classes
3.7.3 Specific Notifications
3.7.3.1 Design steps
3.7.3.2 FIFO semaphores
3.7.4 Further Readings
Chapter 4. Creating Threads
4.1 Oneway Messages
4.1.1 Message Formats
4.1.2 Open Calls
4.1.3 Thread-Per-Message
4.1.3.1 Executors
4.1.4 Worker Threads
4.1.4.1 Design choices
4.1.4.2 Event queues
4.1.4.3 Timers
4.1.5 Polling and Event-Driven IO
4.1.5.1 Event-driven tasks
4.1.5.2 Triggering
4.1.6 Further Readings
4.2 Composing Oneway Messages
4.2.1 Composition
4.2.1.1 Representations
4.2.1.2 Stages
4.2.1.3 Scripting
4.2.2 Assembly Line
4.2.2.1 Representations
4.2.2.2 Interfaces
4.2.2.3 Adapters
4.2.2.4 Sinks
4.2.2.5 Connections
4.2.2.6 Linear stages
4.2.2.7 Combiners
4.2.2.8 Collectors
4.2.2.9 Dual output stages
4.2.2.10 Sources
4.2.2.11 Coordination
4.2.3 Further Readings
4.3 Services in Threads
4.3.1 Completion Callbacks
4.3.1.1 Interfaces
4.3.1.2 Implementations
4.3.1.3 Guarding callback methods
4.3.2 Joining Threads
4.3.3 Futures
4.3.3.1 Callables
4.3.4 Scheduling Services
4.3.5 Further Readings
4.4 Parallel Decomposition
4.4.1 Fork/Join
4.4.1.1 Task granularity and structure
4.4.1.2 Frameworks
4.4.1.3 Defining tasks
4.4.1.4 Fibonacci
4.4.1.5 Linking subtasks
4.4.1.6 Callbacks
4.4.1.7 Cancellation
4.4.2 Computation Trees
4.4.2.1 Building and using trees
4.4.3 Barriers
4.4.4 Further Readings
4.5 Active Objects
4.5.1 CSP
4.5.1.1 Processes and channels
4.5.1.2 Composition
4.5.1.3 JCSP
4.5.1.4 Dining philosophers
4.5.2 Further Readings
Concurrent Programming in Java™: Design Principles and Patterns, Second Edition By Doug Lea Publisher: Addison Wesley Pub Date: October 01, 1999 ISBN: 0-201-31009-0 Pages: 432 In Concurrent Programming in Java, Second Edition, you will find thoroughly updated coverage of the Java 2 platform and new or expanded coverage of: • Memory model • Cancellation • Portable parallel programming • Utility classes for concurrency control The Java platform provides a broad and powerful set of APIs, tools, and technologies. One of its most powerful capabilities is the built-in support for threads. This makes concurrent programming an attractive yet challenging option for programmers using the Java programming language. This book shows readers how to use the Java platform's threading model more precisely by helping them to understand the patterns and tradeoffs associated with concurrent programming. You will learn how to initiate, control, and coordinate concurrent activities using the class java.lang.Thread, the keywords synchronized and volatile, and the methods wait, notify, and notifyAll. In addition, you will find detailed coverage of all aspects of concurrent programming, including such topics as confinement and synchronization, deadlocks and conflicts, state-dependent action control, asynchronous message passing and control flow, coordinated interaction, and structuring web-based and computational services. The book targets intermediate to advanced programmers interested in mastering the complexities of concurrent programming. Taking a design pattern approach, the book offers standard design techniques for creating and implementing components that solve common concurrent programming challenges. The numerous code examples throughout help clarify the subtleties of the concurrent programming concepts discussed. Copyright Acknowledgments Chapter 1. Concurrent Object-Oriented Programming Section 1.1. Using Concurrency Constructs Section 1.2. Objects and Concurrency Section 1.3. Design Forces Section 1.4. Before/After Patterns
Section 2.1. Immutability Chapter 3. State Dependence Section 2.5. Using Lock Utilities Chapter 2. Exclusion Section 2.2. Synchronization Section 2.3. Confinement Section 2.4. Structuring and Refactoring Classes Section 3.1. Dealing with Failure Section 3.2. Guarded Methods Section 3.3. Structuring and Refactoring Classes Section 3.4. Using Concurrency Control Utilities Section 3.5. Joint Actions Section 3.6. Transactions Section 3.7. Implementing Utilities Chapter 4. Creating Threads Section 4.1. Oneway Messages Section 4.2. Composing Oneway Messages Section 4.3. Services in Threads Section 4.4. Parallel Decomposition Section 4.5. Active Objects Copyright Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book and Addison-Wesley was aware of a trademark claim, the designations have been printed in initial caps or all caps. Duke™ designed by Joe Palrang. Sun Microsystems, Inc. has intellectual property rights relating to implementations of the technology described in this publication. In particular, and without limitation, these intellectual property rights may include one or more U.S. patents, foreign patents, or pending applications. Sun, Sun Microsystems, the Sun Logo, and all Sun, Java, Jini, and Solaris based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. UNIX is a registered trademark in the United States and other countries, exclusively licensed through X/Open Company, Ltd. As used in this book, the terms "Java virtual machine" and "JVM" mean a virtual machine for the Java platform. THIS PUBLICATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON- INFRINGEMENT.
THIS PUBLICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN; THESE CHANGES WILL BE INCORPORATED IN NEW EDITIONS OF THE PUBLICATION. SUN MICROSYSTEMS, INC. MAY MAKE IMPROVEMENTS AND/OR CHANGES IN ANY TECHNOLOGY, PRODUCT, OR PROGRAM DESCRIBED IN THIS PUBLICATION AT ANY TIME. The author and publisher have taken care in the preparation of this document, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein. Library of Congress Card Number 99-066823 Copyright © 2000 by Addison Wesley Longman, Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in the United States of America. Published simultaneously in Canada. Text printed on recycled and acid-free paper. 2 3 4 5 6 7 - MA - 02 01 00 99 Second printing, November 1999 Acknowledgments This book began as a small set of Web pages that I put together in spring 1995, while trying to make sense of my own early attempts to use Java concurrency features in experimental development efforts. Then it grew; first on the World Wide Web, where I extended, expanded, and removed patterns to reflect my and other people's increasing experience with Java concurrency; and now into this book, which places patterns within the broader perspective of concurrent software development. The web pages also live on, but they now serve as a supplement to the conceptual presentations best suited to book form. There have been many changes along the way, in a process that has benefited from commentary, suggestions, errata reports, and exchanges with many kind and knowledgeable people. These include Ole Agesen, Tatsuya Aoyagi, Taranov Alexander, Moti Ben-Ari, Peter Buhr, Bruce Chapman, Il- Hyung Cho, Colin Cooper, Kelly Davis, Bruce Eckel, Yacov Eckel, Saleh Elmohamed, Ed Falis, Randy Farmer, Glenn Goldstein, David Hanson, Jyrki Heikkinen, Alain Hsiung, Jerry James, Johannes Johannsen, Istvan Kiss, Ross Knippel, Bil Lewis, Sheng Liang, Jonathan Locke, Steve MacDonald, Hidehiko Masuhara, Arnulf Mester, Mike Mills, Trevor Morris, Bill Pugh, Andrew Purshottam, Simon Roberts, John Rose, Rodney Ryan, Joel Rosi-Schwartz, Miles Sabin, Aamod Sane, Beverly Sanders, Doug Schmidt, Kevin Shank, Yukari Shirota, David Spitz, David Stoutamire, Henry Story, Sumana Srinivasan, Satish Subramanian, Jeff Swartz, Patrick Thompson, Volker Turau, Dennis Ulrich, Cees Vissar, Bruce Wallace, Greg Wilson, Grant Woodside, Steve Yen, and Dave Yost, as well as people who submitted anonymous electronic mail commentary.
The members of Ralph Johnson's patterns seminar (especially Brian Foote and Ian Chai) read through early forms of some patterns and suggested many improvements. Raj Datta, Sterling Barrett, and Philip Eskelin of the New York City Patterns Group, and Russ Rufer, Ming Kwok, Mustafa Ozgen, Edward Anderson, and Don Chin of the Silicon Valley Patterns Group performed similar valuable service for preliminary versions of the second edition. Official and unofficial reviewers of the first- and second-edition manuscripts made helpful comments and suggestions on tight schedules. They include Ken Arnold, Josh Bloch, Joseph Bowbeer, Patrick Chan, Gary Craig, Desmond D'Souza, Bill Foote, Tim Harrison, David Henderson, Tim Lindholm, Tom May, Oscar Nierstrasz, James Robins, Greg Travis, Mark Wales, Peter Welch, and Deborra Zukowski. Very special thanks go to Tom Cargill for his many insights and corrections, as well as for permission to include a description of his Specific Notification pattern. Very special thanks also go to David Holmes for, among many contributions, helping to develop and extend material for tutorials that in turn became included in the second edition. Rosemary Simpson contributed numerous improvements in the course of creating the index. Ken Arnold patiently helped me deal with FrameMaker. Mike Hendrickson and the editorial crew at Addison-Wesley have been continually supportive. This book would not have been possible without the generous support of Sun Labs. Thanks especially to Jos Marlowe and Steve Heller for providing opportunities to work collaboratively on fun and exciting research and development projects. Thanks above all to Kathy, Keith, and Colin for tolerating all this. Doug Lea, September, 1999 Chapter 1. Concurrent Object-Oriented Programming This book discusses some ways of thinking about, designing, and implementing concurrent programs in the Java™ programming language. Most presentations in this book assume that you are an experienced developer familiar with object-oriented (OO) programming, but have little exposure to concurrency. Readers with the opposite background — experience with concurrency in other languages — may also find this book useful. The book is organized into four coarse-grained chapters. (Perhaps parts would be a better term.) This first chapter begins with a brief tour of some frequently used constructs and then backs up to establish a conceptual basis for concurrent object-oriented programming: how concurrency and objects fit together, how the resulting design forces impact construction of classes and components, and how some common design patterns can be used to structure solutions. The three subsequent chapters are centered around use (and evasion) of the three kinds of concurrency constructs found in the Java programming language: Exclusion. Maintaining consistent states of objects by preventing unwanted interference among concurrent activities, often using synchronized methods. State dependence. Triggering, preventing, postponing, or recovering from actions depending on whether objects are in states in which these actions could or did succeed, sometimes using monitor methods Object.wait, Object.notify, and Object.notifyAll.
Creating threads. Establishing and managing concurrency, using Thread objects. Each chapter contains a sequence of major sections, each on an independent topic. They present high- level design principles and strategies, technical details surrounding constructs, utilities that encapsulate common usages, and associated design patterns that address particular concurrency problems. Most sections conclude with an annotated set of further readings providing more information on selected topics. The online supplement to this book contains links to additional online resources, as well as updates, errata, and code examples. It is accessible via links from: http://java.sun.com/Series or http://gee.cs.oswego.edu/dl/cpj If you are already familiar with the basics, you can read this book in the presented order to explore each topic in more depth. But most readers will want to read this book in various different orders. Because most concurrency concepts and techniques interact with most others, it is not always possible to understand each section or chapter in complete isolation from all the others. However, you can still take a breadth-first approach, briefly scanning each chapter (including this one) before proceeding with more detailed coverage of interest. Many presentations later in the book can be approached after selectively reading through earlier material indicated by extensive cross-references. You can practice this now by skimming through the following preliminaries. Terminology. This book uses standard OO terminological conventions: programs define methods (implementing operations) and fields (representing attributes) that hold for all instances (objects) of specified classes. Interactions in OO programs normally revolve around the responsibilities placed upon a client object needing an action to be performed, and a server object containing the code to perform the action. The terms client and server are used here in their generic senses, not in the specialized sense of distributed client/server architectures. A client is just any object that sends a request to another object, and a server is just any object receiving such a request. Most objects play the roles of both clients and servers. In the usual case where it doesn't matter whether an object under discussion acts as a client or server or both, it is usually called a host; others that it may in turn interact with are often called helpers or peers. Also, when discussing invocations of the form obj.msg(arg), the recipient (that is, the object bound to variable obj) is called the target object. This book generally avoids dealing with transient facts about particular classes and packages not directly related to concurrency. And it does not cover details about concurrency control in specialized frameworks such as Enterprise JavaBeans™ and Servlets. But it does sometimes refer to branded software and trademarked products associated with the Java™ Platform. The copyright page of this book provides more information. Code listings. Most techniques and patterns in this book are illustrated by variants of an annoyingly small set of toy running examples. This is not an effort to be boring, but to be clear. Concurrency constructs are often subtle enough to get lost in otherwise meaningful examples. Reuse of running examples makes small but critical differences more obvious by highlighting the main design and implementation issues. Also, the presentations include code sketches and fragments of classes that illustrate implementation techniques, but are not intended to be complete or even compilable. These classes are indicated by leading comments in the listings. Import statements, access qualifiers, and even methods and fields are sometimes omitted from listings when they can be inferred from context or do not impact relevant functionality. The protected
qualifier is used as a default for non-public features whenever there is no particular reason to restrict subclass access. This emphasizes opportunities for extensibility in concurrent class design (see § 1.3.4 and § 3.3.3). Classes by default have no access qualifier. Sample listings are sometimes formatted in nonstandard ways to keep them together on pages or to emphasize the main constructions of interest. The code for all example classes in this book is available from the online supplement. Most techniques and patterns in this book are illustrated by a single code example showing their most typical forms. The supplement includes additional examples that demonstrate minor variations, as well as some links to other known usages. It also includes some larger examples that are more useful to browse and experiment with online than to read as listings. The supplement provides links to a package, util.concurrent, that contains production- quality versions of utility classes discussed in this book. This code runs on the Java 2 Platform and has been tested with 1.2.x releases. Occasional discussions, asides, and footnotes briefly mention changes from previous releases, potential future changes known at the time of this writing, and a few implementation quirks to watch out for. Check the online supplement for additional updates. Diagrams. Standard UML notation is used for interaction and class diagrams (see the Further Readings in § 1.1.3). The accompanying diagrams (courtesy of Martin Fowler) illustrate the only forms used in this book. Other aspects of UML notation, methodology, and terminology are not specifically relied on.
Most other diagrams show timethreads in which free-form gray curves trace threads traversing through collections of objects. Flattened arrowheads represent blocking. Objects are depicted as ovals that sometimes show selected internal features such as locks, fields, and bits of code. Thin (usually labeled) lines between objects represent relations (normally references or potential calls) between them. Here's an otherwise meaningless example showing that thread A has acquired the lock for object X, and is proceeding through some method in object Y that serves as a helper to X. Thread B is meanwhile somehow blocked while entering some method in object X: 1.1 Using Concurrency Constructs This section introduces basic concurrency support constructs by example and then proceeds with a walk-through of the principal methods of class Thread. Other concurrency constructs are briefly
described as they are introduced, but full technical details are postponed to later chapters (mainly § 2.2.1 and § 3.2.2). Also, concurrent programs often make use of a few ordinary Java programming language features that are not as widely used elsewhere. These are briefly reviewed as they arise. 1.1.1 A Particle Applet ParticleApplet is an Applet that displays randomly moving particles. In addition to concurrency constructs, this example illustrates a few of the issues encountered when using threads with any GUI-based program. The version described here needs a lot of embellishment to be visually attractive or realistic. You might enjoy experimenting with additions and variations as an exercise. As is typical of GUI-based programs, ParticleApplet uses several auxiliary classes that do most of the work. We'll step through construction of the Particle and ParticleCanvas classes before discussing ParticleApplet. 1.1.1.1 Particle The Particle class defines a completely unrealistic model of movable bodies. Each particle is represented only by its (x, y) location. Each particle also supports a method to randomly change its location and a method to draw itself (as a small square) given a supplied java.awt.Graphics object. While Particle objects do not themselves exhibit any intrinsic concurrency, their methods may be invoked across multiple concurrent activities. When one activity is performing a move and another is invoking draw at about the same time, we'd like to make sure that the draw paints an accurate representation of where the Particle is. Here, we require that draw uses the location values current either before or after the move. For example, it would be conceptually wrong for a draw operation to display using the y-value current before a given move, but the x-value current after the move. If we were to allow this, then the draw method would sometimes display the particle at a location that it never actually occupied.
分享到:
收藏