1. atomic value
java5 begins, provides classes atomic operation, such as AtomicInteger, AtomicLong etc.
These classes provide methods such as atomic incrementAndGet such operations.
If you want the singular complex operation is required for loop processing compareAndSet
do { // .. 计算 } while (!atomicLong.compareAndSet(old, new));
It provides updateAndGet and accumulateAndGet method in java8
atomicLong,updateAndGet(x -> Max.max(x, observed));
atomicLong.accumulateAndGet(observed, Math::max);
It also provides a method corresponding to the original value: getAndUpdate, getAndAccumulate
------------------------------------------------------
When a large number of threads access the same original value, because the number of retries optimistic locking too much can lead to performance degradation
Java8 aims to provide a LongAdder and LongAccumulator resolve the issue
The idea of the initial value becomes more neutral elements, different threads may operate on different elements of the calculation, then the final result of the merger operation.
E.g:
LongAccumulator adder = new LongAccumulator (Long::sum, 0); adder.accumulate(value);
In this case included in the plurality of neutral LongAccumulator elements a1, a2 ... aN. The initial value of the neutral element in this example are zero. When calling method accumulate accumulation One of value, wherein the variables are updated as ai = ai op v. In this Strength ai = ai + v;
The method call to get the last time, the result is a1 op a2 op ... aN. As in the above example a1 + a2 + ... aN
------------------------------------------------------
java8 also added StampedLock class implements optimistic reading
Will get a stamp when you call tryOptimisticRead method, and detects when reading the value stamp is valid, you can use this value, otherwise you will get a write lock blocking all read locks
Example:
public class Vector { private int size; private Object[] elements; private StampedLock lock = new StampedLock(); public Object get(int n) { long stamp = lock.tryOptimisticRead(); Object[] currentElements = elements; int currentSize = size; if (!lock.validate(stamp)) { // Someone else had a write lock stamp = lock.readLock(); // Get a pessimistic lock currentElements = elements; currentSize = size; lock.unlockRead(stamp); } return n < currentSize ? currentElements[n] : null; } ...
2.ConcurrentHashMap improvements
1. Update the value
concurrentHashMap update the value of the time though is thread-safe, but when calculating the updated value of the guarantee because it is not thread-safe, the updated value may be wrong.
A remedy is to replace the use of
Example:
1 do { 2 oldValue = map.get(word); 3 newValue = oldValue == null ? 1 : oldValue + 1; 4 } while (!map.replace(key, oldValue, newValue));
In addition the use of atomic object may also be used, e.g. CuncurrentHashMap <String, LongAdder>
map.putIfAbsent(word, new LongAdder()); map.get(word).increment();
If desired complex calculations, compute the new method may be calculated by a function value
map.compute(word, (k, v) -> v == null ? 1 : v + 1);
xxxIfPresent and xxxIfAbsent represent existing methods do not yet exist or a case where the value of the value before the operation
merge method can do some special operation key when the first addition, the second parameter represents the initial value when the key is not yet present
map.merge(word, 1L, (existingValue, newValue) -> existingValue + newValue); map.merge(word, 1L, Long::sum);
--------------------------------------------------------------------------
2. bulk data operations
· Search for recipients will each key a function until the function returns a non-null, search terminates and returns a function result
· Reduce cumulative function will be provided by the combination of all key-value pairs
· Foreach on all key application for a function
Each operation has four versions:
• operation Keys: key operation
• operation Values: on the value of the operation
• operation: Operation of keys and values
• operation Entries: Map.Entry for object manipulation.
To search, for example, has the following methods:
U searchKeys(long threshold, BiFunction<? super K, ? extends U> f)
U searchValues(long threshold, BiFunction<? super V, ? extends U> f)
U search(long threshold, BiFunction<? super K, ? super V,? extends U> f)
U searchEntries(long threshold, BiFunction<Map.Entry<K, V>, ? extends U> f)
threshold for parallel threshold, if the number of elements contained exceeds the threshold, the operation will be executed in parallel, if you want to always be single-threaded execution, use Long.MAX_VALUE
foreach addition to the above methods reduce and form, another form there may be provided a converter function, the application will first converter function, then the result is passed to the consumer function
map.forEach(threshold, (k, v) -> k + " -> " + v, // Transformer System.out::println); // Consumer
Integer maxlength = map.reduceKeys(threshold, String::length, // Transformer Integer::max); // Accumulator
For int, long and double, reduce operation provides a methodology. Beginning toXXX, converts the input values need to be a primitive type, and to specify a default value and accumulator function
long sum = map.reduceValuesToLong(threshold, Long::longValue, // Transformer to primitive type 0, // Default value for empty map Long::sum); // Primitive type accumulator
-----------------------------------------------------------------------------
3. Set view
java8 concurrenHashSet class is not provided, but may be obtained by mapping a class through false value concurrentHashMap
NewKeySet static method returns a Set <K> object, which is actually ConcurrentHashMap <K, Boolean> encapsulated object.
Set<String> words = ConcurrentHashMap.<String>newKeySet();
If you already have a map, keySet method returns a Set of all keys, but you can not add elements to this set, the corresponding value because they can not be added to the map
Thus, a method of receiving a default value keySet may solve the above problem, adding elements to the default values set by this
Set<String> words = map.keySet(1L); words.add("Java");
key=java, value = 1L
3. The parallel array operations
Arrays offer many parallel operations
parallelSort sort may be performed in parallel, and may be specified range
1 String contents = new String(Files.readAllBytes( 2 Paths.get("alice.txt")), StandardCharsets.UTF_8); // Read file into string 3 String[] words = contents.split("[\\P{L}]+"); // Split along nonletters 4 Arrays.parallelSort(words);
1 values.parallelSort (values.length / 2, values.length); // Sort the upper half
parallelSetAll method will be calculated for each parameter based on the calculated values of the functions provided and update
Arrays.parallelSetAll(values, i -> i % 10); // Fills values with 0 1 2 3 4 5 6 7 8 9 0 1 2 . . .
parallelPrefix each array element with the association operation specified prefix accumulation
Suppose array [1, 2, 3, 4, ...], executing the Arrays.parallelPrefix (values, (x, y) -> x * y) after the array is the result
[1, 1 × 2, 1 × 2 × 3, 1 × 2 × 3 × 4, ...]
4. Future completed
In the past, methods to obtain results for the Future get, and the call will always get blocked waiting for the results to return
CompletableFuture <T> provides the function "when the result is available, then in the manner provided in process"
1 CompletableFuture<String> contents = readPage(url); 2 CompletableFuture<List<String>> links = contents.thenApply(Parser::getLinks);
thenApply method is not blocked, it will return another Future object, when the first Future object is completed, its results will be issued getLinks method
Future pipeline Similarly Steam line, through one or more conversion process, a terminating end of the last operation.
As a start code may be pipelined
1 CompletableFuture<String> contents 2 = CompletableFuture.<strong>supplyAsync</strong>(() -> blockingReadPage(url));
There is also a method runAsync receiving Runnable parameter returns CompletableFuture <void>
Then you can call thenApply or thenApplyAsync method, run another operation in the same thread or another thread.
These final steps are finished, the results need to be stored somewhere, you need a termination of operations, such as:
1 CompletableFuture<Void> links 2 = CompletableFuture.supplyAsync(() -> blockingReadPage(url)) 3 .thenApply(Parser::getLinks) 4 .thenAccept(System.out::println);
The method of receiving a thenAccept Consumer Interface (return type void), no need to call the get method Future Ideally
Here are some common methods:
The method thenCompose do is, it is supposed that there are two call chains, T-> CompletableFuture <U> and U-> CompletableFuture <V> in the case of the successive calls, merged T-> CompletableFuture <V>
Similar conventional method is as follows: