I just started working with notify, synchronized and wait, and it almost works, but only when I let the second Thread sleep() for 1 ms. You can see my console output at the end.
My main:
public static void main(String[] args) {
InfoPaket paket = new InfoPaket();
TestThread testThread = new TestThread(paket);
TestThread2 testThread2 = new TestThread2(paket);
}
My "Lock" Class
public class InfoPaket {
String info;
char infoDataSign;
boolean newInfo = false;
public synchronized boolean isNew(){
if (!newInfo){
try {
System.out.println("waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return newInfo;
}
public synchronized String getInfo() {
newInfo = false;
return info;
}
public synchronized void setInfo(String info) {this.info = info;
newInfo = true;
notify();
}
My two test Thread
1.
public class TestThread implements Runnable {
InfoPaket info;
int i = 0;
public TestThread(InfoPaket info) {
this.info = info;
new Thread(this,"TestThread").start();
}
public void run() {
while(true){
i++;
getInfo();
}
}
void getInfo(){
info.isNew();
System.out.println("he got it... " + info.getInfo() + " " + i);
}
2.
public class TestThread2 implements Runnable{
InfoPaket info;
Thread t;
int i = 0;
public TestThread2(InfoPaket info) {
this.info = info;
t = new Thread(this,"TestThread");
t.start();
}
public void run() {
while(i < 500000){
i++;
setInfo();
}
}
void setInfo(){
info.setInfo("lelaoao");
System.out.println("here " + i);
try {
t.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Here my results which are very clear and nice (except for the start):
waiting
he got it... lelaoao 1
waiting
here 1
here 2
he got it... lelaoao 2
waiting
here 3
he got it... lelaoao 3
waiting
here 4
he got it... lelaoao 4
waiting
here 5
he got it... lelaoao 5
waiting
here 6
he got it... lelaoao 6
And so on..
But putting the 2. thread everytime asleep slows down the program,
but without it I get something strange that I can't explain to myself:
waiting
here 1
he got it... lelaoao 1
he got it... lelaoao 2
waiting
here 2
here 3
he got it... lelaoao 3
he got it... lelaoao 4
waiting
here 4
here 5
here 6
here 7
here 8
here 9
here 10
he got it... lelaoao 5
he got it... lelaoao 6
waiting
You code is working as expected (as coded), except - 1) You have some bad code 2) You may have misunderstood the concept.
Let me first start by saying what your code is doing:
You have a InfoPaket which is shared among your 2 thread and hold info about packet, and keeps track whether new info is received or not.
Then your have TestThread which will check if new info is received or not, if new info is not recieved then it will wait and once new info is received then you will print the info (which is always "lelaoao") along with your loop counter, like this he got it... lelaoao 23
Then your have TestThread2 which will set the info and notify the waiting thread and then print the loop counter of this thread like this - "here " + i.
Now, most important thing for your understand is that thread scheduling is unexpected and depends on underlying OS thread scheduling mechanism as well as JVM implementation, so you cannot expect that if thread 2 has set info then then certainly thread 1 will execute, you can try to enforce it putting Thread.sleep(1) or Thread.yeild(), please note that Thread.yeild() is not portable and it is good that you are not using it and should not be use it, instead of it you should use Thread.sleep(1)
Now let come to bad code and some important concepts:
Bad code
The most wrong thing you were doing is you were starting a new thread from the constructor, don't ever try to start a new thread from the constructor because it will cause your reference to leak even before your constructor has completed. Read this excellent article.
You don't need a reference of current thread in TestThread2 because you can directly do Thread.sleep(1); which will cause current thread to sleep.
You were printing System.out.println("he got it... " + info + " " + i); and System.out.println("here " + i); from your main thread, however you should print these from synchronized block to ensure that there is no interleaving, because in absence of synchronization interleaving could occur and you could see he got it... lelaoao 3 before here 3 which is logically wrong.
Now, below is the fixed code which will consistent produce correct result (considering your are giving thread 1 chance to run once thread 2 has set info), output is also placed in the end.
InfoPaket.java
public class InfoPaket {
String info;
char infoDataSign;
boolean newInfo = false;
public synchronized boolean isNew() {
if (!newInfo) {
try {
System.out.println("waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return newInfo;
}
public synchronized void getInfo(int i) {
newInfo = false;
System.out.println("he got it... " + info + " " + i);
}
public synchronized void setInfo(String info, int i) {
this.info = info;
newInfo = true;
System.out.println("here " + i);
notify();
}
public static void main(String[] args) {
InfoPaket paket = new InfoPaket();
TestThread testThread = new TestThread(paket);
TestThread2 testThread2 = new TestThread2(paket);
new Thread(testThread, "testThread").start();
new Thread(testThread2, "testThread2").start();
}
}
TestThread.java
public class TestThread implements Runnable {
InfoPaket info;
int i = 0;
public TestThread(InfoPaket info) {
this.info = info;
}
public void run() {
while (true) {
i++;
getInfo(i);
}
}
void getInfo(int i2){
info.isNew();
info.getInfo(i2);
}
}
TestThread2.java
public class TestThread2 implements Runnable {
InfoPaket info;
int i = 0;
public TestThread2(InfoPaket info) {
this.info = info;
}
public void run() {
while (i < 500000) {
i++;
setInfo(i);
}
}
void setInfo(int i2) {
info.setInfo("lelaoao", i2);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output:
waiting
here 1
he got it... lelaoao 1
waiting
here 2
he got it... lelaoao 2
waiting
here 3
he got it... lelaoao 3
waiting
here 4
he got it... lelaoao 4
waiting
here 5
he got it... lelaoao 5
waiting
here 6
he got it... lelaoao 6
waiting
here 7
he got it... lelaoao 7
waiting
here 8
he got it... lelaoao 8
waiting
here 9
he got it... lelaoao 9
waiting
here 10
he got it... lelaoao 10
waiting
here 11
he got it... lelaoao 11
waiting
here 12
he got it... lelaoao 12
waiting
here 13
he got it... lelaoao 13
waiting
here 14
he got it... lelaoao 14
waiting
here 15
he got it... lelaoao 15
waiting
here 16
he got it... lelaoao 16
waiting
here 17
he got it... lelaoao 17
waiting
here 18
he got it... lelaoao 18
waiting
here 19
he got it... lelaoao 19
waiting
here 20
he got it... lelaoao 20
waiting
here 21
he got it... lelaoao 21
waiting
here 22
he got it... lelaoao 22
waiting
here 23
he got it... lelaoao 23
waiting
here 24
he got it... lelaoao 24
waiting
here 25
he got it... lelaoao 25
waiting
here 26
he got it... lelaoao 26
waiting
here 27
he got it... lelaoao 27
waiting
here 28
he got it... lelaoao 28
waiting
here 29
he got it... lelaoao 29
waiting
here 30
he got it... lelaoao 30
waiting
here 31
he got it... lelaoao 31
Important concepts to be clear about
I think you might be missing some concept so you are thinking output to be crazy.
Once you have set the info using thread 2 there is no guarantee that thread 1 will run because thread scheduling is unexpected and depends on underlying OS thread scheduling mechanism as well as JVM implementation, I have highlighted more point about this in the start with Thread.yield() and Thread.sleep(). With that note, if you don't use Thread.sleep(1) then you just can't expect output to be consistent, as I have shown below.
When you do Thread.sleep then it doesn't release the lock, if that thread is acquiring some lock.
Once you do notify(); then you can't expect the waiting thread to be "runnable" immediately and the thread which is acquiring the lock will not release immediately release the lock as soon as notify(); is called, lock will be released only once that synchronized block/method is finished.
If you don't do Thread.sleep(1) in your 2nd thread then you can't expect the consistent output, and reasons I have explained above.
OP's comment:
Do you know any a more efficent way of transmitting data from on
thread to an other one?
Either you have "shared memory" or "message passing"; shared memory is what we are doing in this case, and if you want to go for message passing then you can go for Java API like blocking queue (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html) implementation, but that's becomes all together different story.
Related
So I have a simple code that I want to print the value I 10 times with Thread1, after that 10 times of Thread2 and at the end, print the count ( it should be 20). I am using the ".join()" but the result is executing random times of Thread1 and Thread2 and then the Sum is correct. How can is it possible to print first all the Thread's1 loop and then the Tread's2 ??
class MyClass extends Thread {
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
for(int i=0; i<10; i++) {
incount();
System.out.println(Thread.currentThread().getId()+" value : " + i);
}
}
}
public class SimpleThreads {
static int count=0;
public static void main(String[] args) {
MyClass thread1 =new MyClass();
MyClass thread2 =new MyClass();
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : "+count);
}
}
The Result :
11 value : 0
10 value : 1
11 value : 1
10 value : 2
11 value : 2
10 value : 3
11 value : 3
11 value : 4
11 value : 5
11 value : 6
11 value : 7
11 value : 8
11 value : 9
10 value : 4
10 value : 5
10 value : 6
10 value : 7
10 value : 8
10 value : 9
Sum : 20
You are starting Thread2 before calling the join() on thread1.
That is why your both threads are basically running simultaneously and your join is not affecting the run() of any other the 2 threads.
Try to change your start and join calling code to something like this;
try{
thread1.start();
thread1.join();
thread2.start();
}
You shouldn't need to call join() on thread2 in this case.
If you want thread2 to start after thread1 terminates, then of-course you can simply wait for thread1 to terminate and then launch thread2. But then, what is the point of using threads?
If you want to launch thread1 and thread2 at the same time and still have thread2 wait until thread1 terminates, you can use one of Java's many concurrency utilities, such as Semaphore
The below code demonstrates the use of Semaphore. As you can see, just as in the code in your question, both threads - thread1 and thread2 - are launched at the same time. In the run() method of class MyClass, the code tries to acquire the semaphore. Method acquire() will block, i.e. it will not return, until it succeeds in acquiring the semaphore. Hence the first thread that manages to acquire the semaphore will run, while the other thread will wait until the first thread releases the semaphore. Note that I create the semaphore with only one permit which means that only one thread can acquire the semaphore at any one time. If you change the 1 to a 2 in the call to the Semaphore constructor, you will get exactly the same behavior as in your original code in your question, i.e. both threads will run simultaneously because both can immediately acquire the semaphore.
Note also that since I am using a semaphore, I don't need to call Thread.join() at all in order to have one thread wait until the other completes, but since you want to print the "sum" in the "main" thread, the "main" thread needs to wait, but it only needs to wait for the second thread to terminate.
Here is the code:
import java.util.concurrent.Semaphore;
class MyClass extends Thread {
private Semaphore semaphore;
public MyClass(Semaphore semaphore) {
this.semaphore = semaphore;
}
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 10; i++) {
incount();
System.out.println(Thread.currentThread().getId() + " value : " + i);
}
}
catch (InterruptedException xInterrupted) {
xInterrupted.printStackTrace();
}
finally {
semaphore.release();
}
}
}
public class SimpleThreads {
static int count = 0;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(1);
MyClass thread1 = new MyClass(semaphore);
MyClass thread2 = new MyClass(semaphore);
thread1.start();
thread2.start();
try {
thread2.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : " + count);
}
}
And here is the output obtained when running the above code:
13 value : 0
13 value : 1
13 value : 2
13 value : 3
13 value : 4
13 value : 5
13 value : 6
13 value : 7
13 value : 8
13 value : 9
14 value : 0
14 value : 1
14 value : 2
14 value : 3
14 value : 4
14 value : 5
14 value : 6
14 value : 7
14 value : 8
14 value : 9
Sum : 20
public class ThreadText
{
public static void main(String[] args)
{
windows w=new windows();
Thread t1=new Thread(w);
Thread t2=new Thread(w);
Thread t3=new Thread(w);
Thread t4=new Thread(w);/*four threads*/
t1.start();
t2.start();
t3.start();
t4.start();
}
}
i want to use four windows to sale 1000 tickets
class windows implements Runnable
{
int tickets=1000;
public void run()
{
synchronized(this)
{
while(tickets>0)
{
System.out.println(Thread.currentThread().getName()+" is saling"+tickets);
tickets--;
}
}/*i think problem is here*/
}
}
when i don't use synchronized ,all threads run,but results are wrong.
some tickets number are same.the correct result is that every window gets different ticket number.
Thanks
When you synchronize the entire loop, the first thread will get the lock and will count down to 0. The other 3 threads will wait until first thread releases the lock, at which point there's nothing left for them to do. In effect, the result is single-threaded.
To work correctly, you need to synchronize inside the loop, so the other threads can work too.
However, the first thread may still be too fast, so that it ends up doing all the work. To better simulate what you want, add a delay outside the synchronize block (making a sale takes time, you know). Added minimum delay of 1ms in the code below.
And finally, Java naming convention is for class names to start with an Uppercase letter, so it should be named Windows.
class Windows implements Runnable {
private int tickets = 1000;
#Override
public void run() {
String threadName = Thread.currentThread().getName();
for (;;) { // loop forever
synchronized (this){
if (this.tickets == 0)
break;
System.out.println(threadName + " is saling " + this.tickets);
this.tickets--;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
break;
}
}
}
}
OUTPUT
Thread-0 is saling 1000
Thread-2 is saling 999
Thread-3 is saling 998
Thread-1 is saling 997
Thread-0 is saling 996
Thread-1 is saling 995
Thread-2 is saling 994
Thread-3 is saling 993
Thread-0 is saling 992
Thread-1 is saling 991
Thread-3 is saling 990
Thread-2 is saling 989
. . .
Thread-2 is saling 11
Thread-1 is saling 10
Thread-0 is saling 9
Thread-3 is saling 8
Thread-0 is saling 7
Thread-1 is saling 6
Thread-2 is saling 5
Thread-1 is saling 4
Thread-0 is saling 3
Thread-3 is saling 2
Thread-2 is saling 1
You do need to synchronize due to the tickets member being accessed by multiple threads. But because you are basing the run method on while tickets > 0, only 1 thread will ever run until the end. One solution would be to tie the execution of the thread to another variable and have the run method just decrement tickets once, then sleep so other threads can have a chance to run. For example, if you refactor your windows class as follows, then it will do what I think you want it to do.
class windows implements Runnable {
volatile boolean finished = false;
int tickets = 1000;
public void run() {
while(!finished) {
synchronized(this) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()+" is selling " + tickets);
tickets--;
if (tickets <= 0) {
finished = true;
}
}
}
try {
Thread.sleep(10);
}
catch(InterruptedException ex) {
}
}
}
}
What you are experiencing is known as a race condition. That means due to the order of threads operating, you can get two threads thinking they decremented something but only one did, etc.
To address this, you have two options:
synchronized -- which is pretty heavy handed, and unless you put it at the smallest critical section is going to be too much.
AtomicInteger -- which makes sure that the integer is incremented or decremented safely across threads.
To fix your example and still use synchronized, your code should look like this:
class windows implements Runnable
{
int tickets=1000;
public void run()
{
while(tickets>0)
{
synchronized(this)
{
System.out.println(Thread.currentThread().getName()+" is saling"+tickets);
tickets--;
}
}
}
}
Of course, the down side to that is you have to remember to synchronize all access to the variable.
Using AtomicInteger the process is much easier to control:
class windows implements Runnable
{
AtomicInteger tickets = new AtomicInteger(1000);
public void run()
{
while(tickets.get() > 0)
{
System.out.println(Thread.currentThread().getName()
+ " is saling" + tickets.decrementAndGet());
}
}
}
From your code I understand that you are trying to replicate a Sales Window in Real Life for the Tickets.
Analogy (Look at the Image Link at the bottom of answer):
A place for sales of Tickets (Say, concert Tickets). This place has multiple Sections/Windows from where the exchange of money happens and the concert ticket is provided. Behind the Window there is a person that actually takes the money and gives u the ticket. Since in your example there is nothing related to money, so this is just a one sided exchange. Basically the person behind the window gives the ticket when ever a customer comes (Customer coming is like thread getting executed in your example).
There are only limited finite number of Ticket, each having a unique ticket number between 1 to 1000.
Your code has same instance of Runnable Window. And this same instance is provided for execution to all threads (All different Instances of Thread).
So your Real Life Design becomes like :
That the same person will give you the tickets from Window 1, 2, 3 etc. But at one time only one window can be taken care by this person.
So making your code effectively to run as Single Processer/Core code but poorer performance than the sequential code as the thread switching (if occurred) will have more overheads.
Now lets say we had multiple sales person - One for each window. Then the question becomes of NOT selling the same ticket by different sales person (Race Condition).
For this all the sales person have to take a ticket from a box one at a time. I.E. the part of getting the ticket is the only part that needs to be synchronized. This would be best achieved by Atomic Integers. Other answers have more than required chunk of code with in their synchronized blocks. This part has been answered (as per me) by #Berin Loritsch reply.
class TicketSeller /* Not windows*/ implements Runnable {
AtomicInteger tickets = new AtomicInteger(1000);
public void run() {
while (tickets.get() > 0) {
System.out.println(Thread.currentThread().getName()
+ " is saling" + tickets.decrementAndGet());
}
}
}
public class ThreadText {
public static void main(String[] args) {
Thread t1 = new Thread(new TicketSeller());
Thread t2 = new Thread(new TicketSeller());
Thread t3 = new Thread(new TicketSeller());
Thread t4 = new Thread(new TicketSeller());
/*four threads, four windows from where the ticket can be provided by 4
different TicketSellers*/
t1.start();
t2.start();
t3.start();
t4.start();
}
}
With this when a different thread comes into execution or multiple threads run in parallel the thread is not put to unnecessary sleep (And sleep doesn't even confirm avoiding of the race condition, by the way) and is blocked from execution for only a limited area of the code, i.e. tickets.get().
Of course you can go a few steps ahead an optimize this even more. But that would require a lot more deeper understanding and complex thinking. E.g. Sales person is allocated a certain number of tickets. And ticket shuffling happens so that to optimize that maximum number of tickets are sold in quickest execution time by something managing the tickets that each SalePerson has.
Ticket Sale Window Example :
https://www.google.com/imgres?imgurl=https%3A%2F%2Fimage.shutterstock.com%2Fimage-photo%2Fthree-windows-stadium-ticket-offices-260nw-1776188525.jpg&imgrefurl=https%3A%2F%2Fwww.shutterstock.com%2Fsearch%2Ftickets%2Bwindow&tbnid=BW8bA0aSqJTxaM&vet=12ahUKEwiVvvrmp47zAhU6g0sFHW8TCekQMygEegUIARC9AQ..i&docid=QQwLjL01dRWDoM&w=390&h=280&q=Ticket%20Sale%20Window&ved=2ahUKEwiVvvrmp47zAhU6g0sFHW8TCekQMygEegUIARC9AQ
I am trying to make a program that runs several parallel readers and writers. I start some threads in a loop using ExecutorService class, the run() method of the Writer class just call two methods StartWrite()and EndWrite() and for the Reader class, StartRead() and EndRead(). These methods are wrapped in a monitor.
Here's the monitor:
public class RWMonitorAN {
static int readers = 0;
static boolean writing = false;
public static RandomAccessFile f;
public static int n = 0;
private final ReentrantLock mylock = new ReentrantLock();
private final Condition toWrite = mylock.newCondition();
private final Condition toRead = mylock.newCondition();
public RWMonitorAN()
{
try { f = new RandomAccessFile("datos.dat", "rw"); } catch (IOException e) {}
}
void StartRead() {
mylock.lock();
try
{
if (writing)
try {
toRead.wait();
toWrite.wait();
} catch (InterruptedException e) {}
readers++;
try
{
f.seek(0);
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
System.out.println();
} catch (IOException e) { e.printStackTrace(); }
}
finally { mylock.unlock(); }
}
void EndRead() {
mylock.lock();
try
{
readers--;
if (readers == 0)
toWrite.signal();
}
finally { mylock.unlock(); }
}
void StartWrite() {
mylock.lock();
try
{
if (writing || readers != 0)
try {
toWrite.wait();
} catch (InterruptedException e) {}
writing = true;
try
{
f.writeInt(n);
} catch(IOException e) {}
n++;
}
finally { mylock.unlock(); }
}
void EndWrite() {
mylock.lock();
try
{
writing = false;
toWrite.signal();
toRead.signal();
}
finally { mylock.unlock(); }
}
But there's a problem: the program ends before the expected number of data is written and read. For example, if I start 20 writer and 20 reader threads, I expect 20 numbers to be written and read, but only 10~ are. If I run the program again (datos.dat would be already created) it keeps writing and reading and then 20 numbers are written.
Test:
1st run
Written in the last executed thread: 0 1 2 3 4
Read in the last executed thread: 0 1 2 3 4
2nd run
Written in the last executed thread: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Read in the last executed thread: 0 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
What's wrong? How can I make it work properly?
EDIT: I tried printing the number of readers every time a reader finishes reading and the same number of readers is being printed several times. Shouldn't this not be happening? readers-- is executed in a lock protected section of the code.
You are catching your exceptions everywhere and not reporting them anywhere nor do anything else to serve them. The first thing to "make it work properly" would probably be to check if there are exceptions called. For example, if you use more than one iterators on one data structure in Java it will probably throw concurrentModificationException at the start, to prevent unexpected behaviour in the future.
What is the point of using multiple readers from a file if, as it appears, you set every new one to the very beginning of a file with seek(0)? And your reader appears to try to read the whole file
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
and your writer tries to read a single int in
f.writeInt(n);
so if you started n threads I would not expect n numbers to be read.
Finally, have you considered what happens when you start another writer/reader after startRead unlocked mylock but before EndRead locked it again? Why not to put the logic from EndRead just at the end of startRead method then?
I tried to write a programme for testing the effect of the execution of parent/child threads in java! why is the number of the active threads below 3? What happens to the other threads. It makes me think that Java can have millions of threads but only a few of them can be active. Is that correct or is there something else?
public class ManyThreadsTester {
static int threadCount = 0;
static class recursiveRunnable implements Runnable{
#Override
public void run() {
System.out.println(threadCount);
// Arrives up to infinity if the System.exit(0) statement is absent!
try {
System.out.println("Active threads before: " + Thread.activeCount());
//Always prints 2
Thread.sleep(40);
threadCount++;
new Thread(new recursiveRunnable()).start();
} catch (InterruptedException ex) {
Logger.getLogger(ManyThreadsTester.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Active threads after: " + Thread.activeCount());
//Always prints 3
}
}
public static void main(String... args) throws InterruptedException{
Thread th = new Thread(new recursiveRunnable());
th.start();
Thread.sleep(5000);
System.out.print("FINAL ACTIVE THREAD COUNTS: " + Thread.activeCount());
//prints 2
System.exit(0);
}
}
Because you threads immediately quit after spawning children. You would get higher numbers if you add a delay at the end:
new Thread(new recursiveRunnable()).start();
Thread.sleep(10000);
Output:
...
Active threads before: 30
28
Active threads before: 31
29
Active threads before: 32
30
...
I just have started learning threads and come upon misunderstanding of how they work.
Here is my class:
public class MyThread extends Thread {
private static int NUM = 0;
private int id;
public MyThread() {
id = NUM++;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new MyThread().start();
}
}
public void run() {
System.out.println(id + " started");
try {
Process p = Runtime.getRuntime().exec("javac -version");
p.waitFor();
} catch (Exception e) {
System.out.println("Call a doc!");
}
System.out.println(id + " finished");
}
}
/*
Just a sidenote.
I am creating new javac process just to slow an application down.
Simple System.out.println(…) is a way faster.
*/
Why do I always get all "… started" messages at first and after that "… finished" messages? No matter how many threads have I started, I always see:
0 started
1 started
2 started
3 started
4 started
5 started
6 started
7 started
8 started
9 started
0 finished
1 finished
3 finished
4 finished
8 finished
5 finished
2 finished
6 finished
9 finished
7 finished
Isn't the purpose of threads to parallelize execution?
Maybe I need to synchronize something? Or made careless mistake? Or…?
Explain, please.
UPDATE:
Why don't I see, let's say:
0 started
1 started
0 finished
2 started
1 finished
2 finished
Thank you all for treatment.
Looks ok. You can see from your output that the threads are interleaving. threads are getting started, get context-switched, and get picked by the scheduler, you can see where thread 8 jumps ahead of thread 5, for instance. If all the numbers were in order consistently it would be strange but this seems fine.
Use sleep time, like Peter Lawrey suggests, so you can alter how long each thread takes more easily. As your example stands, starting a process takes so much time it seems reasonable all your threads should get started before any finish.
The threads are parallel. Otherwise you would see each thread "finished" before the next one "started"
A simple way to slow down a thread is to use Thread.sleep(10*1000); to sleep for 10 seconds (10,000 milli-seconds)
EDIT: a simple way to see threads interleaving is to have a fixed size thread pool.
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
final int id = i;
pool.submit(new Callable<Void>() {
public Void call() throws InterruptedException {
System.out.println(id + " started");
Thread.sleep(1000);
System.out.println(id + " finished");
return null;
}
});
}
Prints
0 started
1 started
2 started
3 started
0 finished
4 started
1 finished
5 started
2 finished
6 started
3 finished
7 started
4 finished
8 started
5 finished
6 finished
9 started
7 finished
8 finished
9 finished
If you put a simple loop to count from 1 to 20 in the run() method you may see the interleaving of the execution better.
There is a difference between multi-threading and parallel processing... check this out...
If you want to see a "random" starting and ending you might want to add a
Thread.sleep(new Random().nextInt(1000));
or similar to the threads.