Java Concurrency in Practice
All
Stack Overflow 149
This Year
Stack Overflow 11
This Month
Stack Overflow 34
It's old, but the material holds up well since it covers a lot of fundamentals
- Think Java (programming, foundational; free) https://greenteapress.com/wp/think-java/
- Think Data Structures (programming, foundational; free) https://greenteapress.com/wp/think-data-structures/
- Effective Java (classic) https://www.amazon.co.uk/Effective-Java-Joshua-Bloch/dp/0134...
- Java Concurrency in Practice (classic) https://www.amazon.co.uk/Java-Concurrency-Practice-Brian-Goe...
- Continuous Delivery in Java (essential) https://www.amazon.co.uk/Continuous-Delivery-Java-Daniel-Bry...
I bought Java Concurrency in Practice as a result of this problem and found they discuss an issue very much like this one in Chapter 7: Cancellation and shutdown which can be summarised by the quote
As the HttpClient is blocking socket IO that does not support interruption so I have a two pronged approach. I allocate my
httpClient
, I check for interruption just before the actualhttpClient.execute()
call and in myunsubscribe()
method interrupt the thread and then callhttpClient.getConnectionManager().shutdown();
. This seems to take care of my problem and was a very simple change. No more interleaving issues!I also set the boolean
unsubscribe
field tovolatile
as suggested which I shouldve done before - this alone however would not have solved the issueThere are no such thing as "static classes" in java. There are inner static classes, but i presume that your question its not about this type of classes.
Classes are loaded once per classloader not per Virtual Machine, this is an important diference, for example applications server like tomcat have different classloaders per application deployed, this way each application is independent (not completely independent, but better than nothing).
The effects for multithreading are the effects of shared data structures in multithreading, nothing special in java. There are a lot of books in this subject like http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 (centered in java) or http://pragprog.com/book/pb7con/seven-concurrency-models-in-seven-weeks (that explain difference concurrency models, really interesting book)
I don't mean this as a flippant answer, but: Java Concurrency In Practice, buy it now...
But to be more serious, you are now quickly getting into a very hairy testing scenario. I don't believe that you are going to have to get into using
java.util.concurrent.ExecutorService
, but if you are going to communicate between threads, you need to be conscious of having thread-safe communication channels (simpleList
s,MessageQueue
s, database tables, etc...) between each simulation thread.Buy yourself Java Concurrency in Practice , it really describes everything about Java and multithreading (and what can totally go wrong). It i written by one of the Lead Architects of Java back in the Sun days and the programmer of the java.util.concurrent framework.
As it happens I was just reading about this this morning on my way to work in Java Concurrency In Practice by Brian Goetz. Basically he says you should do one of two things
Propagate the
InterruptedException
- Declare your method to throw the checkedInterruptedException
so that your caller has to deal with it.Restore the Interrupt - Sometimes you cannot throw
InterruptedException
. In these cases you should catch theInterruptedException
and restore the interrupt status by calling theinterrupt()
method on thecurrentThread
so the code higher up the call stack can see that an interrupt was issued.In general, yes, it is possible to see a field in a partially constructed state if the field is not published in a safe manner. In the particular case of your question, the
volatile
keyword is a satisfactory form of safe publication. According to Java Concurrency in Practice:For more information, see the following:
Thread-safety is already guaranteed by atomic variables.
volatile
is redundant if you won't reassign the variable. You can replacevolatile
withfinal
here:At this moment, it's absolutely thread-safe. No "memory consistency issues" might happen with the variable. But using proper thread-safe components doesn't mean that the whole class/program is thread-safe. Problems might take place if interactions between them are incorrect.
volatile
variables can only guarantee visibility. They don't guarantee atomicity.As Brian Goetz writes (emphasis mine):
From the docs of the
java.util.concurrent.atomic
package:There are 2 points when reasoning about thread safety of a particulcar class :
Shared state of
Example
class consists only from oneThing
object.setThing
by one thread isn't seen by other threads so they can work with stale data. NPE is also acceptable cause initial value ofthing
during class initialization isnull
.Thing
class throughuse
method without its source code. HoweverExample
invokesuse
method without any synchronization so it should be, otherwiseExample
isn't thread safe.As a result
Example
isn't thread safe. To fix point 1 you can either addvolatile
tothing
field if you really need setter or mark it as final and initialize in constructor. The easiest way to ensure that 2 is met is to markuse
assynchronized
. If you marksetThing
withsynchronized
as well you don't needvolatile
anymore. However there lots of other sophisticated techniques to meet point 2. This great book describes everything written here in more detail.From Java Concurrency in Practice 15.2.3 CAS support in the JVM :
It's well described in Java Concurrency in Practice:
Static initialization
Although there are some good answers already posted, but here is what I found while reading Java Concurrency in Practice Chapter 3 - Sharing Objects.
Quote from the book.
Book states ways to safely publish mutable objects:
The last point refers to using various mechanisms like using concurrent data structures and/or using synchronize keyword.
An explanation is given with an example in Java Concurrency In Practice chapter 4 section 4.3.5.
The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this(p.x, p.y).
What does it mean is, if you did not have a private constructor and you implement copy constructor in following way:
Now assume that thread A is having the access to SafePoint p is executing above copy constructor's this(p.x, p.y) instruction and at the unlucky timing another thread B also having access to SafePoint p executes setter set(int x, int y) on object p. Since your copy constructor is accessing p's x and y instance variable directly without proper locking it could see inconsistent state of object p.
Where as the private constructor is accessing p's variables x and y through getter which is synchronized so you are guaranteed to see consistent state of object p.
[1] https://youtu.be/dGVqrGmwOAw?t=23m57s [2] https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz...
The answer also depends a bit on what exactly you want to do. If you're mainly interested in web apps, it's one thing, "big data" is another world altogether, mobile (Android) has its own ecosystem, etc.
All of that said, here are some thoughts:
Generics and the newer Collections related stuff is one area that changed a lot. There's online documentation at:
https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz...
To get started with the Java 8 stuff, a book like "Java 8 in Action" would be good.
https://www.amazon.com/Java-Action-Lambdas-functional-style-...
Another good intro the Java 8 era stuff is
https://www.amazon.com/Beginning-Java-Language-Features-Expr...
And to make it even harder, Java 9 just dropped, so there's even more new stuff. I just picked up this book myself, but haven't had a lot of time to dig into it yet.
https://www.amazon.com/Java-Programmers-4th-Deitel-Developer...
For frameworks, Spring and Hibernate are both still popular and it wouldn't hurt to brush up on both of those. Spring Boot in particular has caught on for a lot of Java developers.
https://www.amazon.com/Spring-Boot-Action-Craig-Walls/dp/161...
Also, Tomcat is still very popular for hosting java Web applications and services of various sorts. JBoss / Wildfly is still around, but JEE (as J2EE is now known) is not as popular as in the past (even though it has actually improved a LOT).
Play and Dropwizard are two more frameworks you might want to familiarize yourself with
https://www.playframework.com/
http://www.dropwizard.io/1.1.4/docs/
In terms of tools, Eclipse is still popular, IntelliJ is probably the most popular Java IDE these days, and Netbeans seems to have faded from view a bit. Ant has fallen out of favour for builds, with most devs now using either Maven or Gradle. Read up on / play around with both of those and you'll be in good shape there.
Also, Java shops have also been affected by the overall move to "The Cloud" and you can't really ignore that either. If you haven't already, you'll probably want to familiarize yourself with AWS and the AWS SDK.
If you want to work/play in the "big data" space, you'll need some combination of Hadoop, Kafka, Spark, Hive, Storm, Flume, HBase, Impala, etc., etc., etc.
I know this is a cross post from here... but, I think one of the best Java books is Java Concurrency in Practice by Brian Goetz. A rather advanced book - but, it will wear well on your concurrent code and Java development in general.
If you dislike Times New Roman, just change the browser default font to Tahoma or something like.
Then start here and click your way through Next link. Then there are the API docs, each with examples in the introductory text. E.g.
ExecutorService
. Then there are books, like Concurrency in Practice.Assuming that your problem is a slow external API, a solution could be the use of either threaded programming or asynchronous programming. By default when doing IO, your code will block. This basically means that if you have a method that does an HTTP request to retrieve some JSON your method will tell your operating system that you're going to sleep and you don't want to be woken up until the operating system has a response to that request. Since that can take several seconds, your application will just idly have to wait.
This behavior is not specific to just HTTP requests. Reading from a file or a device such as a webcam has the same implications. Software does this to prevent hogging up the CPU when it obviously has no use of it.
So the question in your case is: Do we really have to wait for one method to finish before we can call another? In the event that the behavior of
method_two
is dependent on the outcome ofmethod_one
, then yes. But in your case, it seems that they are individual units of work without co-dependence. So there is a potential for concurrency execution.You can start new threads by initializing an instance of the Thread class with a block that contains the code you'd like to run. Think of a thread as a program inside your program. Your Ruby interpreter will automatically alternate between the thread and your main program. You can start as many threads as you'd like, but the more threads you create, the longer turns your main program will have to wait before returning to execution. However, we are probably talking microseconds or less. Let's look at an example of threaded execution.
Calling
main_method
will cause all three methods to be executed in what appears to be parallel. In reality they are still being sequentually processed, but instead of going to sleep whenmethod_one
blocks, Ruby will just return to the main thread and switch back tomethod_one
thread, when the OS has the input ready.Assuming each method takes two 2 ms to execute minus the wait for the response, that means all three methods are running after just 6 ms - practically instantly.
If we assume that a response takes 500 ms to complete, that means you can cut down your total execution time from 2 + 500 + 2 + 500 + 2 + 500 to just 2 + 2 + 2 + 500 - in other words from 1506 ms to just 506 ms.
It will feel like the methods are running simultanously, but in fact they are just sleeping simultanously.
In your case however you have a challenge because you have an operation that is dependent on the completion of a set of previous operations. In other words, if you have task A, B, C, D, E and F, then A, B, C, D and E can be performed simultanously, but F cannot be performed until A, B, C, D and E are all complete.
There are different ways to solve this. Let's look at a simple solution which is creating a sleepy loop in the main thread that periodically examines a list of return values to make sure some condition is fullfilled.
Keep in mind that multithreaded programming is a tricky subject with numerous pitfalls. With MRI it's not so bad, because while MRI will happily switch between blocked threads, MRI doesn't support executing two threads simultanously and that solves quite a few concurrency concerns.
If you want to get into multithreaded programming, I recommend this book: http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601
It's centered around Java, but the pitfalls and concepts explained are universal.
First of all, take a look at this SO on reasons not to use
Vector
. That being said:1)
Vector
locks on every operation. That means it only allows one thread at a time to call any of its operations (get,set,add,etc.). There is nothing preventing multiple threads from modifyingB
s or their members because they can obtain a reference to them at different times. The only guarantee withVector
(or classes that have similar synchronization policies) is that no two threads can concurrently modify the vector and thus get into a race condition (which could throwConcurrentModificationException
and/or lead to undefined behavior);2) As above, there is nothing preventing multiple threads to access
C
s at the same time because they can obtain a reference to them at different times.If you need to protect the state of an object, you need to do it as close to the state as possible. Java has no concept of a thread owning an object. So in your case, if you want to prevent many threads from calling
setSameString
concurrently, you need to declare the methodsynchronized
.I recommend the excellent book by Brian Goetz on concurrency for more on the topic.