The previous chapter says that delegates are one of the most effective strategies for creating thread-safe classes by simply having existing thread-safe classes manage all the state. So this chapter is about how to use the Java Platform Class Library of the concurrent base building module?
5.1 Synchronizing Container classes
Includes vectors and Hashtable, as well as some of the functionally similar classes added in JDK1.2, which are created by factory methods such as Collections.synchronizedxxx. These classes implement thread safety in a way that encapsulates their state and synchronizes each common method so that only one thread can access the state of the container at a time.
About the vector in Java, see the next JDK document, roughly speaking, the implementation of variable-length array function and random access, the inherited parent class is abstractlist, that is, vector and ArrayList is also a list data structure, The difference is that ArrayList will be faster than vector, but ArrayList is not synchronous, if the design involves multi-threading, it is better to use a vector. This is also illustrated in the JDK documentation, where the vector iteration is fast-fail, meaning that if the structure of the vector changes after the iterator is returned, it will throwConcurrentModificationException异常。基本的方法和List系列的集合差不多。关于Vector类用法的例子和Vector类的源码
About Hashtable:java Improvement (25)-----HashTable
-5.1.1 problems with the synchronization container class
This means that when using the synchronization container class, additional client locks are required in some cases to protect the composite operation. Common compound operations on a container include iterations and operation conditions, such as if none were added (check the map for the existence of the key value K, if not, join the two-tuple (k,v)).
The synchronization container class protects each of its methods by its own lock. By obtaining a lock on a container class, you can make GetLast and deletelast atomic operations,
Between the call size and the corresponding get, the length of the vector may change, and the risk will still occur when iterating over the elements in the vector.
This problem is resolved by client-side locking, but it can cause other threads to not access it during the iteration, thereby reducing concurrency.
-5.1.2 iterators and Concurrentmodificationexception
The "just-in-time failure" of an iterator is implemented by linking the change of the counter to the container and if the counter is modified during the iteration, then Hasnext or next throws concurrentmodificationexception. However, this check is performed without synchronization, so you may see a count of failures, and the iterator may not be aware that modifications have occurred. This exception is also thrown in single-threaded code, which is thrown when the object is deleted directly from the container instead of being deleted by Iterator.remove.
-
Note this Implementation is not synchronized. If Multiple threads access a ArrayList instance concurrently, and at least one of the threads modifies the list Structurally, it must be synchronized externally. (A structural modification is any operation this adds or deletes one or more elements, or explicitly resizes the backing A Rray; Merely setting the value of an element was not a structural modification.) This was typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the collections.synchronizedlist
method. Creation time, to prevent accidental unsynchronized access to the list:
list = Collections.synchronizedlist (new ArrayList (...));
For concurrency, if you do not want to lock the container during an iteration, an alternative is to "clone" the container and iterate over the replica.
-5.1.3 Hidden iterators
Although locking can prevent concurrentmodificationexception, remember that all iterations of a shared container need to be locked, but in some cases iterators are hidden, such as:
5.2 Concurrent Container Classes
java5.0 adds Concurrenthashmap and copyonwritearraylist, adding two new types of containers: Queue and Blockingqueue. Queue is used to temporarily save a set of elements waiting to be processed, which provides several implementations, including: Concurrentlinkedqueue and Priorityqueue.
-5.2.1 Concurrenthashmap
Like HashMap, Concurrenthashmap is also a hash-based map, but with a completely different strategy to provide higher concurrency and scalability. Concurrenthashmap does not synchronize each method in the same lock, and does not allow only one thread to access the container at a time, using a segmented lock mechanism, a more granular locking mechanism. See more Concurrenthashmap Summary
-5.2.2 Extra Atomic operation
Because Concurrenthashmap cannot be locked to perform exclusive access, new atomic operations cannot be created using client Gathalai. You may consider using Currentmap. About Currentmap
-5.2.3 copyonwritearraylist
Used instead of synchronizing lists. The thread safety of the copy on Write container is that, as long as a fact-immutable object is published correctly, no further synchronization is required when the object is accessed. Each time a modification is made, a new container copy is created and republished for variability. It is obvious that the underlying array will be copied whenever the container is modified. The copy-on-write container should be used only if the iteration operation is far more than the modification operation. This guideline is a good description of the event notification system:
About Copyonwritearraylist
5.3 Blocking queue and producer-consumer mode
The blocking queue provides a blocking put and take method, as well as an offer and poll method that supports timing. If the queue is full, the put method blocks until there is space available, and if the queue is empty, the take method blocks until an element is available. Blockingqueue simplifies the implementation process of producer-consumer design. About Blockingqueue. Blockingqueue in-depth analysis of Java multithreading (v)
-5.3.1 Example: Desktop Search
The task of the following program producer is to search for files in a file hierarchy that conform to the index criteria and put their names in the work queue, and the consumer's task is to remove the file names from the queue and index them.
-5.3.2 Serial Thread closure
-5.3.3 double-ended queue and work-out
Java6 adds two types of containers, deque and Blockingdeque, which correspond to the double-ended queue in the data structure, enabling efficient insertion and removal at the queue header and queue end. Specific implementations include Arraydeque and Linkedblockingdeque. The double-ended queue is suitable for another correlation mode, that is, work-in-cache. In a work-tight design, each consumer has its own double-ended queue. If a consumer completes all the work in its own double-ended queue, it can secretly get work from the end of the other consumer's double-ended queue.
5.4 Blocking method and interrupt method
Blockingqueue's put and take methods throw a check exception (Checked Exception) interrupted-exception, which is the same as some other methods in the class library, such as Thread.Sleep. When a method throws a interruptedexception, it indicates that the method is a blocking method. Thread provides the interrupt method for breaking threads or whether the query thread has been interrupted. Each thread has a Boolean type of property. When you call a Interruptedexception method in your code, your own method becomes a blocking method and must handle the response to the interrupt. There are two basic options: Delivery interruptedexception and recovery interrupts
5.5 Synchronization Tool Class
In a container class, a blocking queue is a unique class that can be used not only as a container to hold objects, but also to coordinate the control flow of producers and consumers waiting for threads. The blocking queue can be used as a synchronization tool class, and other types of synchronization tool classes also include semaphores, fences, and latching
-5.5.1 Latching
About Countdownlatch
The following procedure gives two common uses of latching:
Starting the goalkeeper allows the main thread to release all the worker threads at the same time (instead of executing one thread on the other, so that the first thread will "lead" after the thread is started), and the end gate enables the main thread to wait for the last one to finish.
-5.5.2 Futuretask
Continue to move Blog: Java multithreaded Programming: Callable, Future and Futuretask analysis (multi-threaded programming four).
The following program uses Futuretask to perform a high-overhead calculation, and the calculation results will be used later. By starting the calculation early, you can reduce the time that is required to wait for the result.
-5.5.3 Signal Volume
The Count Semaphore (counting semaphore) is used to control the number of simultaneous accesses to a particular resource, to implement a resource pool, or to impose boundaries on a container. Java Multithreading Series--principle and example of the semaphore semaphore of "Juc lock" 11
Feel this principle is similar to the operating system in the PV operation, that seems to be what signal volume, do not know and Java this is not the same thing.
-5.5.4 Fences
The previously mentioned lockout is a one-time operation and cannot be reset once it enters the termination state. Java Concurrency Learning Note (iv)-Fence Cyclicbarrier
Another form of fence is the exchanger, which is a two-party fence where the parties exchange data on the fence position. Java thread&concurrency (4): In-depth understanding of exchanger implementation principles
5.6 Example: building an efficient and scalable result cache
This section will develop an efficient and scalable cache for improving a function with high computational overhead. Start with HashMap, then analyze its concurrency flaws and discuss how to fix them.
Then we use Concurrenthashmap to replace HashMap:
The Memoizer3 in the following program will redefine the map used for cached values as concurrenthashmap<a, Future<v>> replace the original concurrenthashmap<a,v>. About the future in Java:Java Threads (vii): Callable and future. The future is an interface, and Futuretask is its implementation.
The current design still has a flaw: there are still two threads that compute the same value (that is, repeated calculations). Because the if code block in the compute method is still a non-atomic "Check and execute" operation, it is still possible for two threads to call compute at the same time to calculate the same value. As shown in the following:
The reason for this problem is that the compound operation ("if not added") is performed on the underlying map object (that is, the Cache.put (arg,ft)), and the object cannot be locked to ensure atomicity. The following procedure resolves this problem:
When the cache is a future instead of a value, it will cause a cache pollution problem: If a calculation is canceled or fails, the calculation will indicate that the computation process has been canceled or failed. In order to resolve this situation, if Memoizer finds that the calculation was canceled or detected with RuntimeException, the future will be removed. Memoizer also does not address cache overdue issues, but can be resolved by using subclasses of Futuretask, specifying a time-out for each result in subclasses, and periodically scanning for overdue elements in the cache. Similarly, the cache cleanup problem has to be resolved.
Summary:
"Java Concurrency Programming Practical" reading notes 4--basic building blocks, synchronization container classes in Java & Concurrent Container classes & Synchronization tool classes, consumer mode