IT Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд

Java concurrent list

Package java.util.concurrent

    Interface Summary

    Class Summary

    Enum Summary

    Exception Summary


    Package java.util.concurrent Description


    Implementations. Classes ThreadPoolExecutor and ScheduledThreadPoolExecutor provide tunable, flexible thread pools. The Executors class provides factory methods for the most common kinds and configurations of Executors, as well as a few utility methods for using them. Other utilities based on Executors include the concrete class FutureTask providing a common extensible implementation of Futures, and ExecutorCompletionService , that assists in coordinating the processing of groups of asynchronous tasks.

    Class ForkJoinPool provides an Executor primarily designed for processing instances of ForkJoinTask and its subclasses. These classes employ a work-stealing scheduler that attains high throughput for tasks conforming to restrictions that often hold in computation-intensive parallel processing.


    Five implementations in java.util.concurrent support the extended BlockingQueue interface, that defines blocking versions of put and take: LinkedBlockingQueue , ArrayBlockingQueue , SynchronousQueue , PriorityBlockingQueue , and DelayQueue . The different classes cover the most common usage contexts for producer-consumer, messaging, parallel tasking, and related concurrent designs.

    Extended interface TransferQueue , and implementation LinkedTransferQueue introduce a synchronous transfer method (along with related features) in which a producer may optionally block awaiting its consumer.

    The BlockingDeque interface extends BlockingQueue to support both FIFO and LIFO (stack-based) operations. Class LinkedBlockingDeque provides an implementation.



    Concurrent Collections

    The «Concurrent» prefix used with some classes in this package is a shorthand indicating several differences from similar «synchronized» classes. For example java.util.Hashtable and Collections.synchronizedMap(new HashMap()) are synchronized. But ConcurrentHashMap is «concurrent». A concurrent collection is thread-safe, but not governed by a single exclusion lock. In the particular case of ConcurrentHashMap, it safely permits any number of concurrent reads as well as a tunable number of concurrent writes. «Synchronized» >Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:

    • they may proceed concurrently with other operations
    • they will never throw ConcurrentModificationException
    • they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.

    Memory Consistency Properties

    • Overview
    • Package
    • >Java™ Platform
      Standard Ed. 8

    Submit a bug or feature
    For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
    Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. Also see the documentation redistribution policy.

    Gu >Last modified: July 19, 2019

    I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

    In the 9 years of running Baeldung, I’ve never, ever done a «sale».
    But. we’ve also not been through anything like this pandemic either.
    And, if making my courses more affordable for a while is going to help a company stay in business, or a developer land a new job, make rent or be able to provide for their family — then it’s well worth doing.
    Effective immediately, all Baeldung courses are 33% off their normal prices!
    You’ll find all three courses in the menu, above, or here.

    1. Overview

    In this quick article, we’ll be looking at the ConcurrentSkipListMap class from the java.util.concurrent package.

    This construct allows us to create thread-safe logic in a lock-free way. It’s ideal for problems when we want to make an immutable snapshot of the data while other threads are still inserting data into the map.

    We will be solving a problem of sorting a stream of events and getting a snapshot of the events that arrived in the last 60 seconds using that construct.

    2. Stream Sorting Logic

    Let’s say that we have a stream of events that are continually coming from multiple threads. We need to be able to take events from the last 60 seconds, and also events that are older than 60 seconds.

    First, let’s define the structure of our event data:

    We want to keep our events sorted using the eventTime field. To achieve this using the ConcurrentSkipListMap, we need to pass a Comparator to its constructor while creating an instance of it:

    We’ll be comparing all arrived events using their timestamps. We are using the comparingLong() method and passing the extract function that can take a long timestamp from the ZonedDateTime.

    When our events are arriving, we need only to add them to the map using the put() method. Note that this method does not require any explicit synchronization:

    The ConcurrentSkipListMap will handle the sorting of those events underneath using the Comparator that was passed to it in the constructor.

    The most notable pros of the ConcurrentSkipListMap are the methods that can make an immutable snapshot of its data in a lock-free way. To get all events that arrived within the past minute, we can use the tailMap() method and pass the time from which we want to get elements:

    It will return all events from the past minute. It will be an immutable snapshot and what is the most important is that other writing threads can add new events to the ConcurrentSkipListMap without any need to do explicit locking.

    We can now get all events that arrived later that one minute from now – by using the headMap() method:

    This will return an immutable snapshot of all events that are older than one minute. All of the above methods belong to the EventWindowSort class, which we’ll use in the next section.

    3. Testing the Sorting Stream Logic

    Once we implemented our sorting logic using the ConcurrentSkipListMap, we can now test it by creating two writer threads that will send one hundred events each:

    Each thread is invoking the acceptEvent() method, sending the events that have eventTime from now to “now minus one hundred seconds”.

    In the meantime, we can invoke the getEventsFromLastMinute() method that will return the snapshot of events that are within the one minute window:

    The number of events in the eventsFromLastMinute will be varying in each test run depending on the speed at which the producer threads will be sending the events to the EventWindowSort. We can assert that there is not a single event in the returned snapshot that is older than one minute:

    And that there are more than zero events in the snapshot that are within the one minute window:

    Our getEventsFromLastMinute() uses the tailMap() underneath.

    Let’s test now the getEventsOlderThatOneMinute() that is using the headMap() method from the ConcurrentSkipListMap:

    This time we get a snapshot of events that are older than one minute. We can assert that there are more than zero of such events:

    And next, that there is not a single event that is from within the last minute:

    The most important thing to note is that we can take the snapshot of data while other threads are still adding new values to the ConcurrentSkipListMap.

    4. Conclusion

    In this quick tutorial, we had a look at the basics of the ConcurrentSkipListMap, along with some practical examples.

    We leveraged the high performance of the ConcurrentSkipListMap to implement a non-blocking algorithm that can serve us an immutable snapshot of data even if at the same time multiple threads are updating the map.

    The implementation of all these examples and code snippets can be found in the GitHub project; this is a Maven project, so it should be easy to import and run as it is.

    Интерфейсы Callable и Future в Java

    Интерфейс Java Callable(java.util.concurrent.Callable) представляет асинхронную задачу, которая может быть выполнена отдельным потоком. Например, можно передать объект Callable в Java ExecutorService, который затем выполнит его асинхронно. Метод call() вызывается для выполнения асинхронной задачи.

    Интерфейс Callable довольно прост. Он содержит единственный метод с именем call().

    Если задача выполняется асинхронно, результат обычно передается обратно через Java Future. Это тот случай, когда Callable передается в ExecutorService для одновременного выполнения.

    Callable использует Generic для определения типа возвращаемого объекта. Класс Executors предоставляет полезные методы для выполнения Java Callable в пуле потоков. Поскольку вызываемые задачи выполняются параллельно, нам нужно дождаться возвращенного объекта.

    Callable задачи возвращают объект java.util.concurrent.Future. Используя объект Java Future, мы можем узнать состояние задачи Callable и получить возвращенный объект. Он предоставляет метод get(), который может ожидать завершения Callable и затем возвращать результат.

    Future предоставляет метод cancel() для отмены связанной задачи Callable. Существует версия метода get(), в которой мы можем указать время ожидания результата, поэтому полезно избегать блокировки текущего потока на более длительное время.

    Существуют методы isDone() и isCancelled() для определения текущего состояния связанной вызываемой задачи.

    Вот простой пример задачи с Callable, которая возвращает имя потока, выполняющего задачу через одну секунду. Мы используем платформу Executor для параллельного выполнения 100 задач и используем Java Future для получения результата представленных задач.

    После того, как мы выполним вышеуказанную программу, вы заметите задержку вывода, потому что метод get() ожидает завершения задачи, вызываемой Java. Также обратите внимание, что есть только 10 потоков, выполняющих эти задачи.

    Вот фрагмент вывода вышеуказанной программы.

    Mon Dec 31 20:40:15 PST 2012::pool-1-thread-1
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-3
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-4
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-5
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-6
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-7
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-8
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-9
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-10
    Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2

    Что делать, если мы хотим переопределить некоторые методы, например, переопределить метод get() для тайм-аута через некоторое время по умолчанию, а не ждать бесконечно?

    В этом случае пригодится класс Java FutureTask, который является базовой реализацией Future.

    Callable против Runnable

    Callable похож на Runnable в том, что оба они представляют задачу, которая предназначена для одновременного выполнения отдельным потоком.

    Callable отличается от Runnable тем, что метод run() не возвращает значение и не может генерировать исключения (только RuntimeExceptions).

    Runnable изначально был разработан для длительного параллельного выполнения, например, одновременный запуск сетевого сервера или просмотр каталога на наличие новых файлов. Интерфейс Callable больше предназначен для одноразовых задач, которые возвращают один результат.

    Средняя оценка / 5. Количество голосов:

    Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.

    Или поделись статьей

    Видим, что вы не нашли ответ на свой вопрос.

    Java Concurrent Collection — CopyOnWriteArrayList Examples

    1. Why CopyOnWriteArrayList?

    You know, ArrayList is not thread-safe so it’s not safe to use in multi-threaded applications. We can achieve thread-safe feature for an ArrayList by using a synchronized wrapper like this:

    However, this synchronized list has a limitation: all of its read and write methods ( add , set , remove , iterator , etc) are synchronized on the list object itself. That means if a thread is executing add() method, it blocks other threads which want to get the iterator to access elements in the list, for example. Also, only one thread can iterate the list’s elements at a time, which can be inefficient. That’s quite rigid.

    What if we want a more flexible collection which allows:

    • Multiple threads executing read operations concurrently.
    • One thread executing read operation and another executing write operation concurrently.
    • Only one thread can execute write operation while other threads can execute read operations simultaneously.

    The CopyOnWriteArrayList >ConcurrentModificationException as per the case of a synchronized list.

    That’s interesting. So how does the CopyOnWriteArrayList implement this concurrent feature?

    2. How does CopyOnWriteArrayList works?

    In addition, a thread must acquire a separate lock before executing a write operation, and all write operations use this same lock so there’s only one write operation can be executed by only one thread at a time. The read operations do not use any lock so multiple threads can execute multiple read operations simultaneously. And of course, read and write operations do not block each other.

    The methods iterator() and listIterator() return an iterator object that holds different copy of the elements, hence the term snapshot iterator. The snapshot iterator doesn’t allow modifying the list while traversing, and it will not throw ConcurrentModificationException if the list is being modified by other thread during the traversal, and the read and write operations work on different copies of elements.

    3. When to Use CopyOnWriteArrayList?

    Having sa >CopyOnWriteArrayList only when the number of write operations is very small as compared to the read operations and the list contains a small number of elements.

    In some cases, we can use CopyOnWriteArrayList as a thread-safe alternative to ArrayList , and to take advantages of its new methods addIfAbsent() and addAllAbsent() , which are explained below.

    4. Understanding CopyOnWriteArrayList API

    • You can pass an array when creating a new CopyOnWriteArrayList object. The list holds a copy of this array, for example:
    • Though a list allows duplicate elements, you can add an element to the list if and only if it is not already in the list, by using the method addIfAbsent(element) . More importantly, this method is thread-safe which means it guarantees no other threads can add the same element at the same time. This method returns true if the element was added. For example:
    • Similarly, the method addAllAbsent(Collection) appends all elements in the specified collection that are not already contained in the list. And more importantly, this method is thread-safe. This method returns the number of elements were added. For example:

    This print Elements added: 1 because the element Banana is already contained in the list1 .

    • The method iterator() returns a generic Iterator that holds a snapshot of the list. This iterator doesn’t support the remove() method.
    • The method listIerator() returns a generic ListIterator that holds a snapshot of the list. This iterator doesn’t support the remove() , set() or add() method.

    And as stated previously, the iterator will not throw ConcurrentModificationException if the list is being modified by another thread while the current thread is traversing the iterator, because a snapshot iterator holds a different copy of elements.

    5. Java CopyOnWriteArrayList Examples

    — Thread Writer adds a number to CopyOnWriteArrayList for every 5 seconds.

    — Thread Reader iterates the list repeatedly with a small delay (10 milliseconds) for every iteration.

    That means the read operations outnumber the write ones, and here’s the full source code of the program:

    Run this program and observe the result. You will see that the reader thread constantly prints out the elements in the list, whereas the writer thread slowly adds a new number to the list. This program runs forever until you press Ctrl + C to stop it.

    Try to change the list implementation from CopyOnWriteArrayList to ArrayList like this:

    Recompile and run the program again, you will see that the reader thread throws ConcurrentModificationException as soon as the writer thread adds a new element to the list. The reader thread die and only the writer thread alive.

    The second example demonstrates how to use CopyOnWriteArrayList in event handling. Consider the following class:

    Suppose this class represents a GUI component which can receives events such as mouse click. The client code can register (subscribe) to receive notification when the event occurs via the following method:

    The components use a CopyOnWriteArrayList object to maintain all registered listeners:

    When an event occurs, the component notifies all of its listeners by iterating the list and invoke the action handler method on each listener, as shown in the fireActionEvent() method:

    The ActionListener interface is defined as follows:

    And the ActionEvent class is implemented as follows:

    Look at the GuiComponent >CopyOnWriteArrayList is used because:

    • It allows two threads can both read and write the list concurrently: one thread adds or removes a listener and the other thread notifies all listeners.
    • The number of listeners is changed infrequently, whereas the number of times the listeners are notified more frequently (the read operations outnumber the write ones).
    • It doesn’t throw ConcurrentModificationException if a thread is adding/removing a listener while another thread is iterating the list of listeners.

    6. Summary

    Other Java Concurrent Collections:

    Other Java Concurrency Tutorials:

    About the Author:

    Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook.

    Читать еще:  Стратегия на javascript
    Ссылка на основную публикацию