public class ReadWriteLock{ private int readers = 0; private int writers = 0; private int writeRequests = 0; public synchronized void lockRead() throws InterruptedException{ while(writers > 0 || writeRequests > 0){ wait(); } readers++; } public synchronized void unlockRead(){ readers--; notifyAll(); } public synchronized void lockWrite() throws InterruptedException{ writeRequests++; while(readers > 0 || writers > 0){ wait(); } writeRequests--; writers++; } public synchronized void unlockWrite() throws InterruptedException{ writers--; notifyAll(); } }
There are 3 threads.
First thread prints 1111... Second prints 2222.. Third prints 33333..
How to schedule threads to print 123123123...?
Create 3 printing threads and store them in array
main:
while(true) {
synchronized(threads[i]){threads[i].notify();}
try {Thread.sleep(10);}
i=(++i) % 3
}
class MyThread extends Thread {
private int value;
void run() {
while(true){
synchronized(this) {
try{wait();}
System.output.print(value);
}
}
}
https://habrahabr.ru/company/luxoft/blog/157273/
https://habrahabr.ru/post/277669/
https://bmwieczorek.wordpress.com/2016/06/21/multiple-approaches-to-concurrent-processing-in-java/
http://fahdshariff.blogspot.com/2016/06/java-8-completablefuture-vs-parallel.html
assume we want to execute 2 long running operations: download content and parse it and we want to do it for the list of resources.
The blog points multiple approaches:
1) Thread(s)
2) ExecutorService to submit Callable and return blocking Future get()
3) ExecutionCompletionService implementing CompletionService to submit Callable and returning Future. CompletionService has take or poll methods waiting and returning first completed task (returned Future’s get() is not blocking)
4) Parallel streams
5) CompletableFuture
The use cases for the fork/join are pretty narrow. It can only be used when the following conditions are met.
1) The data-set is large & efficiently splittable.
2) The operations performed on individual data items should be reasonably independent of each other.
3) The operations should be expensive & CPU intensive.
When the above conditions do not hold, and your use case is more I/O or network intensive then use ExecutorService with CompletableFuture.
CompletableFuture https://blog.cngroup.dk/2015/08/04/completable-future/
examples what we can do with CompletableFuture:
Combine several asynchronous operation
Wait for task completion
Listen to Future completion and react to it success or error completion
Chaining results of dependent futures
http://stackoverflow.com/questions/33944471/forkjointask-vs-completablefuture
In Java 8 there are two ways of starting asynchronous computations - CompletableFuture and ForkJoinTask.
They both seem fairly similar - the inner classes of CompletableFuture even extend ForkJoinTask.
ForkJoinTask is more recommended when you have a big task and want to split it to run in parallel in several sub tasks. The ForkJoin framework uses the work stealing algorithm which will make an efficient use of the threads. On the other hand, CompletableFutures are more appropriate for a Reactive programming model, where you can create pipelines of execution in a sync or async fashion, and have a better control of the threads by using the thread pools of the Executor Service.
Distributing the Work with the ExecutorService
Say you have 100,000 CPU-intensive tasks, and your computer has 8 cores, which means it could run 8 tasks at the same time (aka “in parallel”). If you run them all in one thread, you only get 1/8 the speed. When you create threads, Java will run them on the available cores for you.
However, you don’t want to create 100,000 separate threads all at once, because it would use up a lot of system resources, be hard to manage, and run slowly due to the CPU having to bounce back and forth between all the threads constantly.
A better way would be to create 8 threads, one per core, and distribute the tasks to them as they complete. This is known as a “thread pool”, and it gives you better parallelism and efficiency, but would be complicated to do manually. With Executors, you can do it in one line of code with Executors.newFixedThreadPool(8):
view plaincopy to clipboardprint?
ExecutorService execService = Executors.newFixedThreadPool(8); // 8 threads
for (int i = 0; i < 100000, i++) {
// you can submit a Runnable, or even a Callable and get a Future
// object representing the result
execService.submit(() -> doIntensiveTask(a, b, c));
}
execService.shutdown(); // starts the shutdown process
execService.awaitTermination(2, TimeUnit.HOURS); // Blocks w/timeout
We can see that an Executor is an object that runs Runnable tasks, and the ExecutorService lets you control those tasks. It generally handles creating Threads for you as necessary, and lets you separate the decision of how many threads to run and when, from the logic of your program.
http://blog.takipi.com/java-8-stampedlocks-vs-readwritelocks-and-synchronized/
https://www.youtube.com/watch?v=Xi4OrmWZGCA&feature=youtu.be
http://www.discoversdk.com/blog/threading-and-synchronization-in-java
https://habrahabr.ru/post/319036/
http://www.byteslounge.com/tutorials/java-8-consumer-and-supplier
http://www.byteslounge.com/subcategory/java-concurrency
https://medium.com/@bizzard4/producer-consumer-the-whole-story-e0b4034406f1#.et0r9bpcn
https://github.com/bizzard4/SynchronizationPrimitives
http://www.discoversdk.com/blog/java-atomic-variables-and-concurrentmap
http://docs.oracle.com/javase/tutorial/essential/concurrency/
https://dzone.com/articles/reentrantlock-cheat-sheet
https://github.com/JCTools/JCTools
http://www.slideshare.net/elizarov/ss-61415341 multithreading
http://tutorials.jenkov.com/java-concurrency/concurrency-models.html
http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/
http://www.javatpointtutorial.net/multithreading-examples-programs-with-output/
http://habrahabr.ru/post/143237/
http://habrahabr.ru/post/133981/
http://habrahabr.ru/post/128985/ Fork Join
http://habrahabr.ru/post/73249/ ExecutorService
https://habrahabr.ru/post/272479/
http://codurance.com/2016/08/24/the-java-synchronisers/
http://codingjunkie.net/completable-futures-part1/
http://java.sun.com/docs/books/tutorial/essential/concurrency
http://www.briangoetz.com/pubs.html
http://habrahabr.ru/post/143237/
syncronized locks the object, not the method or code (it means that 2 threads cannot run on the same object).
Constructors cannot be synchronized.
syncronized static void foo() - the lock is associated with Class object
Excessive use of the synchronized keyword may be counterproductive as code scales up. The java.util.concurrent package offers a range of lightweight and flexible tools for most of your needs.
The Semaphore class provides easily understood semantics and powerful capabilities in the form of methods such as acquire(), release(), etc. In addition, you can allow a semaphore to have a specific number of slots for callers to use, after which further callers are blocked.
Concurrent locks such as ReentrantLock() are even more flexible, allowing for a timed retry mechanism and the ability to check the number of outstanding attempts to lock the resource.
CopyOnWriteArrayList is thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the array
ConcurrentMap
SynchronousQueue is a blocking queue in which each insert operation must wait for a corresponding remove operation by another thread, and vice versa. A synchronous queue does not have any internal capacity, not even a capacity of one.
The Runnable interface defines a type of class that can be run by a thread. The only method it requires is run(). http://www.codestyle.org/java/faq-Threads.shtml
One should no longer start a thread on your own in general, because leaving that to the executor service makes all much more controllable
import java.util.*;
import java.util.concurrent.*;
public class SemApp
{
public static void main(String[] args)
{
Runnable limitedCall = new Runnable() {
final Random rand = new Random();
final Semaphore available = new Semaphore(3);
int count = 0;
public void run()
{
int time = rand.nextInt(15);
int num = count++;
try
{
available.acquire();
System.out.println("Executing " +
"long-running action for " + time + " seconds... #" + num);
Thread.sleep(time * 1000);
System.out.println("Done with #" + num + "!");
available.release();
}
catch (InterruptedException intEx)
{
intEx.printStackTrace();
}
} //end of run()
};
for (int i=0; i<10; i++)
new Thread(limitedCall).start();
}
}
------
boolean pleaseStop = false; // The bus pull cord. Object driver = new Object(); // We can synchronize on any Java object. public void pleaseStopTheBus() { // Here in "thread 1", synchronize on the driver object synchronized (driver) { pleaseStop = true; } } public void startTheBus() { new Thread("bus") { public void run() { // Infinitely drive the bus. while (true) { // And here in "thread 2", also synchronize on the driver object synchronized (driver) { if (pleaseStop) { pleaseStop = false; // Reset pull cord. return; // Bus stopped. } } // Take some time driving to the next stop. } } }.start(); }
===========================================================
public class Archiver implements Runnable {
public static AtomicLong count = AtomicLong(0);
public static String[] tasks;
class Task implements Runnable {
Task(String taskId) {
this.taskId = taskId;
}
//...
public void run() {
long delta = something(taskId);
delta += somethingElse(taskId);
delta += commit(taskId);
synchronized(count) {
count.addAndGet(delta);
}
}
}
public void run() {
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(processors);
for(String id : tasks)
pool.execute(new Task(id));
pool.shutdown();
try{
if(!pool.awaitTermination(20, TimeUnit.MINUTES))
throw new InterruptedException("Time Limit Exceeded");
} catch(InterruptedException e) {
e.printStackTrace();
pool.shutdownNow();
System.exit(1);
}
System.out.println(count);
}
public static void main(String[] args) {
tasks = args;
new Thread(new Archiver()).start();
}
}
Synchronizer Types
Barriers
Semaphore
Phasers
Exchangers
Latch
http://weblogs.java.net/blog/cayhorstmann/archive/2011/05/04/dozen-concurrency-pitfalls
http://today.java.net/article/2010/04/14/rethinking-multi-threaded-design-principles-part-2
http://habrahabr.ru/blogs/java/137065/
Threads share the heap and have their own stack space. Threads can be used by either :
- Extending the Thread class
- Implementing the Runnable interface
wait(), notify(), and notifyAll() methods provide a way for threads to communicate
http://www.wilsonmar.com/1threads.htm
Sync
If 2 threads access the class member it is allowed to them to have the local copy, so the value of local copy can be out of sync.
There are two ways to fix this problem.
- Access variable from a synchronized method or block.
- Declare variable volatile.
When variables are declared volatile, they are reconciled with main memory on every access.
By contrast, when synchronized is used, the variables are reconciled with main memory only when the lock is obtained and when the lock is released.
Consider using synchronized if you are updating many variables and do not want the cost of reconciling each of them with main memory on every access.
Futures
http://habrahabr.ru/post/143074/
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/FutureTask.html
https://habrahabr.ru/post/277669/
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html
http://www.vogella.com/tutorials/JavaConcurrency/article.html
https://plumbr.eu/blog/locked-threads/improving-lock-performance-in-java
http://habrahabr.ru/post/272479/ Java 8 parallel
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=jvm+concurrency:
http://tutorials.jenkov.com/java-concurrency/index.html
http://www.ibm.com/developerworks/ru/library/j-jvmc3/index.html
http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/
http://vmlens.com/articles/synchronized-java-util-hashmap-vs-java-util-concurrent-concurrenthashmap/
http://kennethjorgensen.com/blog/2016/introduction-to-completablefutures
http://www.infoq.com/presentations/concurrency-tools-jvm#downloadPdf JVM Concurrency options
http://jug.ru/meetings/828 Multithreading
http://www.javacodegeeks.com/2015/09/java-concurrency-essentials.html
http://www.javacodegeeks.com/2015/09/concurrency-fundamentals-deadlocks-and-object-monitors.html
http://www.ibm.com/developerworks/ru/library/j-concurrencybugpatterns/index.html
https://dzone.com/articles/understanding-thread-interruption-in-java
http://habrahabr.ru/company/golovachcourses/blog/256883/
http://winterbe.com/posts/2015/05/22/java8-concurrency-tutorial-atomic-concurrent-map-examples/
http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/