Java Concurrency - Part 1 : Threads
This post is the first of set of posts about Java Concurrency.
The concurrency is the fact to made several things at the same time using several threads.
A thread, also called Lightweight Process, is treatment unity. Threads executes code in parallel of each other threads currently running. When you've only one processor, there is a thread running at the same time of the others, you only have the impression of concurrency (I don't say it's not useful, I say it's different), but when you've multiple processors, you'll see the power of multithreading. In this case, you can have your threads distributed on the processors of the computer.
In Java, a thread is an instance of the class java.lang.Thread. A Thread can be managed in one of these two ways :
- Directly mapped to a native thread of the operating system. This is used when the operating system provide a preemptive threading system.
- Managed by the virtual machine in a preemptive way.
A preemptive system, is a system in which the threads are managed by a scheduler and can be interrupted at any time to give processor to an other thread. When you program, you doesn't have to pay attention of which type of threads you use, the result will normally be the same. But you've to know that there can differences between operating systems.
There is three very important concepts when doing concurrent programming :
- Atomicity : An operation is said atomic when it cannot be interrupted. There is almost no atomic operations in Java, the only we've is the assignation a = 5, but a = b++ is not atomic. In some cases, you'll have to make atomic some actions with synchronization, we'll see later how to do that.
- Visibility : This occurs when a thread must watch the actions of an other threads by example the termination of the thread. This also implies some kind of synchronization.
- Order of execution : When you have normal program, all you lines of code run in the same order every time you launch the application. This is not the case when you make concurrent programming. You first instruction can followed by an instruction of the thread B or by the first instruction. And that can change every time you launch the application. The order of execution is not guaranteed ! I will certainly repeat that sometimes, but that's important to know.
We'll see these concepts more deeply in the others parts of the set.
Lets start introducing the Thread class in Java. You can create threads in two ways :
- Extends Thread
- Implements Runnable and pass an instance of your news class to the Thread constructor
The first solution isn't a good solution because what you're creating is not a new specialized thread, but several instructions to run in a new Thread, namely a Runnable. Implementing Runnable is also better because Runnable is an interface and so, you can also extends a class and implementing Runnable, that's useful in some cases.
In my examples, I'll always use the second way. So let's declare our first Runnable :
public class MyFirstRunnable implements Runnable{ @Override public void run() { System.out.println("In a thread"); } }
And use it to create a new Thread and start it :
Thread thread = new Thread(new MyFirstRunnable()); thread.start();
The Thread will stopped when the end of the run() will be reached. You cannot force a thread to stop (there is stop() method, but deprecated), we'll see later how to properly stop a thread.
And now, what happens if we add a simple line of code to our program :
Thread thread = new Thread(new MyFirstRunnable()); thread.start(); System.out.println("In the main Thread");
Can you predict the result of this code ? Nobody can't, it's not predictable, you can have :
In a thread In the main Thread
or
In the main Thread In a thread
And we cannot do better than that.
You can use the Runnable several times :
Runnable runnable = new MyFirstRunnable(); for(int i = 0; i < 25; i++){ new Thread(runnable).start(); }
Now, 25 threads are launched.
You can also give names to Thread using the setName() method. You can get the name of the current thread using Thread.currentThread().getName(). Let's do a little example :
public class MySecondRunnable implements Runnable{ @Override public void run() { System.out.printf("I'm running in thread %s \n", Thread.currentThread().getName()); } }
Runnable runnable = new MySecondRunnable(); for(int i = 0; i < 25; i++){ Thread thread = new Thread(runnable); thread.setName("Thread " + i); thread.start(); }
This is the best example to see that the other is unpredictable. Here are two executions on my machine :
1.
I'm running in thread Thread 0 I'm running in thread Thread 1 I'm running in thread Thread 2 I'm running in thread Thread 3 I'm running in thread Thread 4 I'm running in thread Thread 5 I'm running in thread Thread 7 I'm running in thread Thread 14 I'm running in thread Thread 13 I'm running in thread Thread 12 I'm running in thread Thread 11 I'm running in thread Thread 10 I'm running in thread Thread 9 I'm running in thread Thread 8 I'm running in thread Thread 6 I'm running in thread Thread 15 I'm running in thread Thread 16 I'm running in thread Thread 17 I'm running in thread Thread 18 I'm running in thread Thread 19 I'm running in thread Thread 20 I'm running in thread Thread 21 I'm running in thread Thread 22 I'm running in thread Thread 23 I'm running in thread Thread 24
2.
I'm running in thread Thread 0 I'm running in thread Thread 1 I'm running in thread Thread 2 I'm running in thread Thread 3 I'm running in thread Thread 4 I'm running in thread Thread 5 I'm running in thread Thread 6 I'm running in thread Thread 7 I'm running in thread Thread 8 I'm running in thread Thread 9 I'm running in thread Thread 10 I'm running in thread Thread 11 I'm running in thread Thread 12 I'm running in thread Thread 13 I'm running in thread Thread 14 I'm running in thread Thread 15 I'm running in thread Thread 16 I'm running in thread Thread 17 I'm running in thread Thread 18 I'm running in thread Thread 19 I'm running in thread Thread 20 I'm running in thread Thread 21 I'm running in thread Thread 22 I'm running in thread Thread 23 I'm running in thread Thread 24
Like you can see, the order the threads instructions are executed is not guaranteed at all.
So here we are with the first part of this suite of articles about Java Concurrency. In the next post, we'll see the operations you can make directly on threads (stopping, joining, sleeping, ...).
I hope you found that post interesting.
The sources of this post are available here : Java Concurrency Sources Part 1.
Comments
Comments powered by Disqus