I have this code below, that evaluates if three threads are done, and if yes, it continues with the code. The problem is that when I include some sort of print statement before the if statement, it works as usual. However, when I don't include the print, it continues forever. Here it is:
while (!are_we_done) {
System.out.println(are_we_done);
if (thread_arr[0].are_we_done==true && thread_arr[1].are_we_done==true && thread_arr[2].are_we_done==true) {
are_we_done=true;
}
}
Any clue as to what's going on?
Thanks in advance for any help/advice.
The problem was that I had to specify the are_we_done variable in the thread class as volatile.
Your work with threads is awesome - google for 'busy waiting'.
in main thread introduce 'latch = new CountDownLatch(<number of threads>)' variable
pass it into all your threads
on finish of the thread call 'latch.countDown()'
in main thread wait for all spawned threads complete with 'latch.await(...)'
Example:
public static void main(String... args) throws Exception {
Thread[] threads = new Thread[3];
CountDownLatch latch = new CountDownLatch(threads.length);
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new YourRunnable(latch));
threads[i].start();
}
while (!latch.await(1000)) {
System.out.println("Not complete yet");
}
System.out.println("Complete!");
}
public class YourRunndable implements Runnable {
... // fields + constructor
public void run() {
try {
... // do your staff
} finally {
latch.countDown();
}
}
}
Related
I am reading some code in OCA/OCP Java SE 7 Programmer I & II Study Guide, and I got stuck on an example:
package threads;
class Totalizer implements Runnable
{
int total = 0;
public void run(){
synchronized(this){
for(int i = 0; i < 100; i++){
total += i;
}
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t){
try {
System.out.println("Waiting for calculation...");
t.wait();
} catch (InterruptedException e) {}
System.out.println(t.total);
}
}
public static void main(String[] args){
Totalizer t = new Totalizer();
new Tester(t).start();
new Tester(t).start();
new Tester(t).start();
}
}
//
When I run main(), it prints:
waiting for calculation...
waiting for calculation...
waiting for calculation...
and nothing happens, no calculation, nothing. I can't figure out what is wrong with this code.
Two points.
The most obvious one is that you never start the Totalizer runnable, so the notifyAll call is never issued. You need to have a line
new Thread(t).start();
somewhere in your main method. But even if you do that, it won't work reliably, as the wait call may be invoked after the notifyAll call. It may also print the output too early, as the wait call can wake up without a notifyAll as well.
The Javadoc for Object.wait() describes what you need to do:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
So, you can't just call Object.wait just like that, if you want to use it correctly. This is because:
You don't know if the condition was already satisfied earlier, before you started waiting
The wait call may also wake up without a notify call
In your case, you need a condition variable that you can check. For example, you can change your code like this:
class Totalizer implements Runnable
{
int total = 0;
boolean calculationComplete; // Condition to check in wait()
public void run() {
for(int i = 0; i < 100; i++) {
total += i;
}
synchronized (this) {
// Indicate condition for wait() is now true
calculationComplete = true;
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t) {
System.out.println("Waiting for calculation...");
// Loop, terminate when condition is true
while (!t.calculationComplete) {
try {
t.wait();
} catch (InterruptedException e) {}
}
System.out.println(t.total);
}
}
right now i'm trying to get my head arround threads and concurrency,
so i tried to make multiple threads which counts together to 1000.
Example: Thread 1=0, Thread 2=1.Thread 3=2, and so on
As you will see in the code i implemented the Runnable interface and started the threads.
What i can see is that every thread starts the loop only for itself even if i use a synchronized method.
This is the loop "class"
private String threadname;
private int counter;
Task3(String threadname,int counter) {
this.threadname = threadname;
this.counter =counter;
}
private synchronized void compute(int i) {
try {
// "simulate" computation
System.out.println(threadname);
Thread.sleep(100);
System.out.println(" " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
for(int i=0; i <= counter;i++)
compute(i);
}
and in this class i start 4 threads with a for loop and give the method aboce the parameters which is only the thread name and how often they should count...
for(int i=0; i<=3;i++){
Runnable r =new Thread(new Task3("Thread"+i,1000));
Thread t = new Thread(r);
t.start();
}
thanks in advance
Explanation
Synchronized only means that it is ensured that a thread waits before entering the method until another thread has finished executing this method. This means that only one thread, at one time, can be inside of this synchronized method.
This can prevent strange behavior when using non-atomic operations. For example threads catching outdated values, thinking they would be up-to-date.
Solution
If you want that all threads count together you need some kind of shared resource, i.e. the counter. Currently every thread has his own counter. You need one counter in total which is shared among all threads.
A quick and dirty method would be to make the counter static. But you can probably do better with a design like this:
Class which manages the threads:
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
for (int i = 0; i < 3; i++) {
Counter counter = new Counter(demo, 1000);
counter.start();
}
}
// Provide a shared resource for all threads
private int sharedCounter = 0;
// Provide a count method for all threads
// which is synchronized to ensure that no
// strange behavior with non-atomic operations occurs
public synchronized void count() {
sharedCounter++;
}
}
And the Thread class:
public class Counter extends Thread {
private Demo mDemo;
private int mAmount;
public Counter(Demo demo, int amount) {
// Remember the shared resource
mDemo = demo;
mAmount = amount;
}
#Override
public void run() {
for (int i < 0; i < mAmount; i++) {
// Call the count method provided
// by the shared resource
mDemo.count();
// Sleep some millis
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I use spring boot and mysql in a web application.
This application use tomcat
I need to generate a value who will be inserted in the database.
I want to avoid to have multiple tread who access method in the same time.
I would like to know if using synchronized with spring is the way to go for this issue.
You can use synchronized method or synchronized block with single or multiple monitor lock to achieve this. But, there are other ways around like: ExecutorService,Countdown latch, Producer-consumer approach etc.I suggest you do some research and pick the appropriate approach which you find convincing.
As for the synchronized method is concern, Here I have demonstrated a situation where two threads invoke a common method increment() and that common method tries to change a shared data counter between threads.
public class App {
// this is a shared data between two threads.
private int counter = 0;
//this method is invoked from both threads.
private synchronized void increment() {
counter++;
}
public static void main(String[] args) {
App app = new App();
app.doWork();
}
private void doWork() {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
thread1.start();
thread2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The counter is :" + counter);
//output shoud be equal to : 20000
}
}
Now, try removing keyword synchronized from the method increment(), re-compile the code and see the nature of output it produces.
I want to have two threads. One will increment my variable and the other one will show it on the screen just after it is incremented.
I want to use the wait() and notifyAll() functions to do that but I have some problems.
I have written this code, but it stops working at some point (it shows only the first and the last number: 1 and 10).
public class TestClass {
static int x = 0;
public static Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++) {
synchronized (lock) {
lock.wait();
System.out.println(x);
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; i++) {
synchronized (lock) {
x++;
lock.notifyAll();
}
}
}
});
t2.start();
}
}
I have tried adding additional notifyAll() in the first thread and wait() in the second one(t2) but it still doesn't work. How can I do that right?
From JavaDoc:
The awakened threads will not be able to proceed until the current
thread relinquishes the lock on this object. The awakened threads will
compete in the usual manner with any other threads that might be
actively competing to synchronize on this object; for example, the
awakened threads enjoy no reliable privilege or disadvantage in being
the next thread to lock this object.
The thread that you just woke up is not guaranteed to acquire the lock immediately, thus you could have the loop that calls notifyAll() run all its iterations before the other gets woken up.
If you want them to alternate, one way is to have each one take turns waiting
Below is a working solution. Key is in adding an additional flag that will indicate whether the writing thread has the right to write. Note final on the lock object, that is a good practice.
public class TestClass
{
private static int x = 0;
private static final Object lock = new Object();
private static boolean canWrite = false;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++)
{
synchronized(lock)
{
if(!canWrite)
lock.wait();
System.out.println(x);
canWrite = false;
lock.notify();
}
}
}
catch (InterruptedException e) {}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
for(int i = 0; i < 10; i++)
{
synchronized(lock)
{
x++;
canWrite = true;
lock.notify();
lock.wait();
}
}
} catch (InterruptedException ex) {}
}
});
t1.start();
t2.start();
}
}
The pattern is confusing but if you want to try to control threads, I suppose it's a useful exercise.
Change your code to give your thread a good name e.g. "test1" and "test2", say. Run your program and dig out the process ID for it and run
jstack <pid>
(you can find it in the bin directory of the JDK). This is (perhaps) what you will see:
test1 will be waiting one the
lock.wait();
while test2 will waiting on
lock.wait();
as well.
Start at the first iteration. test2 wins and calls notify, which has no effect at all because nothing is waiting on the lock. test2 then starts waiting.
Now test1 can enter and immediately goes into a wait.
If test1 wins the first time, you can get into a cycle that appears to work.
That is why you get the first number (test2 wins first) or the last number (test1 wins).
That's pretty much what it looks like to me, but your jstack will tell you for sure.
PS: Use CountDownLatch and the concurrency package in general.
class myRunnable implements Runnable {
public void run() {
// TODO Auto-generated method stub
System.out.println("run");
}
}
public class TestThread {
public static void main(String[] args) {
Runnable threadJob = new myRunnable();
Thread t = new Thread(threadJob);
t.start();
for (int i = 0; i < 100000; i++) {
System.out.println("main");
}
}
}
Result in the console:
main
main
main
main
...
main
main
main
main
I can't find any "run" word, this means the run method didn't run. Can somebody explain that for me. Thank you.
PS: when i<10, i<100, i<1000, i<10000, I can find the "run" word, but when i<100000 then I can't find the "run" word, that's just weird
Run has been printed out. But your console-buffer is not large enougth.
Change the Console-configuration to unlimited buffer.
First of all, Yes, Your code actually prints "run".
Just make this little change below and You´ll see it.
A more rigorous test, If You can see it in a different way, is to send the strings to a text file instead of the console. You will certanly find the word "run".
class myRunnable implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run");
}
}
public class TestThread {
public static void main(String[] args) {
Runnable threadJob = new myRunnable();
Thread t = new Thread(threadJob);
t.start();
for (int i = 0; i < 100000; i++) {
System.out.println("main");
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Your implementation runs just fine. You just don't see your run message because there hasn't been any thread switch just yet.
The problem is that the action on which you examine the threads is too short. You can insert a Thread.sleep(2000); for example to check it out.
I find this wired that you can't find a run in your output, the thing is that you should understand how the java thread mechanism works, the main thread will not wait for the child thread to complete their work, unless you make it specific, thus whether or not the child complete before the main thread complete (and exit) is not expectancy.
if you do want the main thread to wait for the child thread to complete, you can make it specific by:
t.start();
t.join();
You should have to catch some exception to make this work.
But I think it should be high ratio that you should see a run printed in your original code. because it seems the main thread is more time consuming.
regardless of this, there is nothing to blame if your jvm behave like this. the thread executing order is not insured by the standard anyway.
Simply add a delay of one second within the loop as displayed below:
class myRunnable implements Runnable {
public void run() {
System.out.println("run");
}
}
public class TestThread {
public static void main(String[] args) {
Runnable threadJob = new myRunnable();
Thread t = new Thread(threadJob);
t.start();
for (int i = 0; i < 100000; i++) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}