How to slow a thread down in JAVA - java

I have this class in which I run a for loop 10 times. This class implements Runnable interface. Now in main() I create 2 threads. Now both will run loop till 10. But I want to check loop count for each thread. If t1 is past 7 then make it sleep 1 second so as to let t2 complete. But how to achieve this? Please see the code. I attempted but looks totally foolish. Just how to check the data of a thread ???
class SimpleJob implements Runnable {
int i;
public void run(){
for(i=0; i<10; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
public int getCount(){
return i;
}
}
public class Threadings {
public static void main(String [] args){
SimpleJob sj = new SimpleJob();
Thread t1 = new Thread(sj);
Thread t2 = new Thread(sj);
t1.setName("T1");
t2.setName("T2");
t1.start();
try{
if(sj.getCount() > 8){ // I know this looks totally ridiculous, but then how to check variable i being incremented by each thread??
System.out.println("Here");
Thread.sleep(2000);
}
}catch(Exception e){
System.out.println(e);
}
t2.start();
}
}
Please help

You should use some synchronization object, and not rely on slowing down of threads. I strongly suggest you take a look at one of the classes at java.util.concurrent package. You can use for this CountdownLatch - thread 1 will await on it, and thread 2 will perform the countdown and release the lock, and let thread 1 continue (the release should be done at the end of thread 2 code).

I added a synchronized Block, which can be entered by one thread at a time. Both threads call and enter the method parallel. One thread will win the race and take the lock. After the first thread leaves the block it waits 2 seconds. In this time the second thread can iterate over the loop. I think this behaviour is wanted. If the second thread must not wait 2 seconds, too, you can set some boolean flag, that the first thread finished the block and use this flag in an if statement, which prevents the wait time of the second thread.
class SimpleJob implements Runnable {
int i;
public void run(){
synchronized (this) {
for(i=0; i<8; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
try {
System.out.println("Here");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(i=0; i<2; i++){
System.out.println(Thread.currentThread().getName()+" Running ");
}
}
public int getCount(){
return i;
}
}
public class Threadings {
public static void main(String [] args){
SimpleJob sj = new SimpleJob();
Thread t1 = new Thread(sj);
Thread t2 = new Thread(sj);
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}

If the goal is to run 2 Runnables in parallel (as Threads) and wait for them both to finish, you can, in increasing order of complexity/power:
Use Thread.join (as suggested by #Suraj Chandran but his reply seems to have been deleted)
Use a CountDownLatch (as also suggested by #zaske)
Use ExecutorService.invokeAll()
EDIT ADDED
First, I don't understand what the magic "if you are at 7 then wait for the other" logic is all about. But, to use Thread.join() from your main code, the code would look like
t1.start(); // Thread 1 starts running...
t2.start(); // Thread 2 starts running...
t1.join(); // wait for Thread 1 to finish
t2.join(); // wait for Thread 2 to finish
// from this point on Thread 1 and Thread 2 are completed...

Related

Problems suspending and resuming a thread

I am new to java programming and trying threading for the first time. I have created a thread to print the even numbers, and then a thread to print odd numbers. In the odd number thread there is a suspend() method after the number 11 to be printed. And after that there is another block to print odd numbers from 13 to 21. In main() I joined the 2 threads. In main function first I called thread t1(even number) and then joined it with thread t2(odd number). As there is suspend it will suspend the output after printing 11 it pauses there. But after that when i call t2.resume() that doesn't continue printing 13 to 21. Why it isn't printing the rest? and how can I make it resume?
Here's the code, please take a look:
class Hi extends Thread {
public void run(){
try{
for(int i=0; i<=10; i++){
System.out.println("1st: " + (2*i));
sleep(100);
}
} catch(Exception e){
System.out.println(e);
}
}
}
class Hello extends Thread {
public void run(){
try {
for(int i=0; i<=5; i++){
System.out.println("2nd: " +(2*i+1));
}
suspend();
System.out.println(" Resumes again");
for(int i=6; i<=10; i++){
System.out.println("2nd: " +(2*i+1));
}
} catch(Exception e){
System.out.println(e);
}
}
}
public class thread {
public static void main(String args[]){
Hi t1 = new Hi();
Hello t2 = new Hello();
t1.start();
try {
t1.join();
} catch (Exception e) {
}
t2.start();
t2.resume();
}
}
OUTPUT:
1st: 0
1st: 2
1st: 4
1st: 6
1st: 8
1st: 10
1st: 12
1st: 14
1st: 16
1st: 18
1st: 20
Exception in thread "main" 2nd: 1
java.lang.IllegalThreadStateException
2nd: 3
2nd: 5
2nd: 7
2nd: 9
2nd: 11
at java.base/java.lang.Thread.start(Thread.java:791)
at thread.main(thread.java:57)
After this the program isn't exiting, I have to exit the program manually (ctrl+c) in the terminal.
After this the program isn't exiting, I have to exit the program manually (ctrl+c) in the terminal.
Aside from the fact that you should not be using suspend() and resume(), I believe your problem is a classic race condition. The main thread is calling t2.start() and then t2.resume() but the thread is not suspended yet. The main thread throws an exception and then the t2 thread finishes its printing and calls suspend(). There is no one left to resume it so the thread never finishes and you have to control-c your program.
You should make a couple of change to your example code. First off use wait/notify instead of suspend(). For example, have the Hello thread do:
// t2 thread shouldn't use suspend which is deprecated for good reason
synchronized (this) {
wait();
}
Then in the main thread you need to loop until the thread is in a wait state before notify-ing it. Something like:
while (true) {
if (t2.getState() == State.WAITING) {
synchronized (t2) {
t2.notify();
}
break;
}
Thread.sleep(100);
}
These sorts of thread exercises where one thread is locked stepped with another (aside from a join() at the end) are a bad example of threading IMO.
Couple other comments. You should join() with the Hello thread at the end of your code, never catch Exception if you can help it since it hides exceptions that may be the source of problems (at least print them as #GhostCat recommended), and also always re-interrupt your threads when you catch InterruptedException:
try {
t2.join();
} catch (InterruptedException e) {
// always a good pattern
Thread.currentThread().interrupt();
e.printStackTrace();
}
when i call t2.resume() that doesn't continue printing 13 to 21. Why it isn't printing the rest?
#Gray answered that one. TLDR: Your main thread calls t2.resume() before your t2 thread calls suspend().
I am curious to know what Java version you are using. I'm running JDK11 on macOS, and I can't get your program to throw that java.lang.IllegalThreadStateException, but I'm guessing that in whatever JDK and OS you are using, the exception is thrown when your main thread tries to resume() a thread that isn't suspended.
how can I make it resume?
I would use a Semaphore.
Let the t2 thread wait to acquire() a "permit" from a semaphore, and let the main thread release() a permit to the semaphore at the appropriate time.
I changed your program by replacing the suspend() call with sem.acquire(), and by replacing the resume() call with sem.release(). I also threw a call to Thread.sleep() into the main thread before it releases the semaphore so that you can see the pause. Here's the whole thing:
import java.util.concurrent.Semaphore;
class Hi extends Thread { // This class is exactly the same as yours.
public void run(){
try{
for(int i=0; i<=10; i++){
System.out.println("1st: " + (2*i));
sleep(100);
}
} catch(Exception e){
System.out.println(e);
}
}
}
class Hello extends Thread {
private Semaphore sem; // new member variable
public Hello(Semaphore sem) { // new constructor to set the new member.
this.sem = sem;
}
public void run(){
try {
for(int i=0; i<=5; i++){
System.out.println("2nd: " +(2*i+1));
}
// Wait to "acquire" a permit from the semaphore. This won't
// return until the main thread "releases" a permit _to_ the
// semaphore.
sem.acquire();
System.out.println(" Resumes again");
for(int i=6; i<=10; i++){
System.out.println("2nd: " +(2*i+1));
}
} catch(Exception e){
System.out.println(e);
}
}
}
public class Wonk {
public static void main(String args[]){
// Create a semaphore that initially has 0 "permits."
Semaphore s = new Semaphore(0);
Hi t1 = new Hi();
Hello t2 = new Hello(s);
t1.start();
try {
t1.join();
} catch (Exception e) {
}
t2.start();
waitabit(5000); // Sleep 5 seconds, and then...
s.release(); // ...Release the Hounds!!
}
private static void waitabit(int numMilliseconds) {
try {
Thread.sleep(numMilliseconds);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Why can yielding a thread solve the thread visibility problem in Java

Consider the following code:
public class Test {
static boolean moreLoop = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
while (moreLoop) {
// more loop
}
System.out.println("loop exited");
});
Thread t2 = new Thread(() -> {
moreLoop = false;
});
t1.start();
Thread.sleep(1000); // so we have more confidence t1 runs first
t2.start();
}
}
After running the code, the "loop exited" statement never gets printed. I understand this is because thread 2 puts the updated boolean in the cache of the CPU in which it's running, so thread 1 can not see the change if it's running in a different CPU. If we make the moreLoop variable volatile then "loop exited" will soon be printed.
Here's the thing. If we leave moreLoop non-volatile and write Thread.currentThread().yield(); on the line after // more loop inside the while loop, we will see "loop exited" printed. Using Thread.sleep will achieve the same effect. Why is that? Does thread 1 sync with thread 2 when it is restored?
I ask this question because my company has a WebApp written in Java that never uses volatile on the shared hash maps and the code has been working for years. My guess is that because the HTTP threads are managed by tomcat, they might get scheduled out after finishing one HTTP request and before serving the next one, just like what I described in the above paragraph. Is this possibly the reason why the code works?
Edit: If we don't use either volatile or yiled/sleep, it seems thread 1 can still see the change made by thread 2 as long as the change by thread 2 is made before the while loop starts. For example, after running the following code
public class Test {
static boolean moreLoop = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println("thread 1 started");
for (long i = 0; i < 10_000_000_000L; ++i); // takes around 3 seconds on my machine
System.out.println("thread 1 warmup finished");
while (moreLoop) {
// more loop
}
System.out.println("loop exited");
});
Thread t2 = new Thread(() -> {
System.out.println("thread 2 started");
moreLoop = false;
System.out.println("thread 2 finished");
});
t1.start();
Thread.sleep(1000); // so we have more confidence t1 runs first
t2.start();
}
}
it prints the following on my machine
thread 1 started
thread 2 started
thread 2 finished
thread 1 warmup finished
loop exited
We don't have any synchronization. Well, you may argue System.out.println does the synchronization. But after I removed all println statements except "loop exited", the code could still print "loop exited". How come thread 1 could see the change made by thread 2?

Why do I have an issue with synchronization? [duplicate]

This question already has answers here:
synchronized block for an Integer object
(3 answers)
Closed 5 years ago.
Why doesn't variable named 'count' finally equal to 20000?
public class Main {
private Integer count = 0;
public void increment() {
synchronized (count) {
count++;
}
}
public static void main(String[] args) {
Main app = new Main();
app.doWork();
}
public void doWork() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
t1.start();
t2.start();
System.out.println(count);
}
It seems that thread loses the variable but when does it happen? The same happens in a case of using AtomicInteger too.
P.S. could you please recommend a good course with exercises for learning multithreading in Java?)
Because start creates a new thread, and when you print the count you aren't sure the thread execution is finished.
t1.start();
t2.start();
System.out.println(count); // Here you don't know if t1 and t2 ended their execution
Join threads to wait for them to complete the task:
t1.start();
t2.start();
t1.join(); // wait for t1 to finish
t2.join(); // wait for t2 to finish
System.out.println(count); // 20000
Note: You'll have to handle InterruptedException on join calls.
You synchronize on count. But your code changes count. Different threads synchronizing on different objects don't guarantee atomicity.
Use a separate final monitor object to synchronize on.
See also #BackSlash 's answer for making sure you print the correct end result.
Edit
His answer comes down to : if you print the result without waiting for the threads to finish on your main thread you'll see some intermediate result, or possibly even 0.
So you need to call join(), which blocks until the thread finishes, on both threads before printing the end result.

Java Thread join() behavior

public class RunTest {
public static int counter = 0;
static class RunnerDec implements Runnable{
public void run(){
for(int i=0;i<5000; i++){
counter--;
}
}
}
static class RunnerInc implements Runnable{
public void run(){
for(int i=0;i<5000; i++){
counter++;
}
}
}
public static void main(String[] args) {
RunnerDec rd = new RunnerDec();
RunnerInc ri = new RunnerInc();
Thread t1 = new Thread(rd);
Thread t2 = new Thread(ri);
t1.start();
t2.start();
try{
t1.join(); // this will stop the main thread until t1 is done incrementing 5000 times
t2.join(); // this will stop the main thread until t2 is done incrementing 5000 times
}catch(Exception e){
e.printStackTrace();
}
System.out.println(counter);
}
}
I expect the result to be 0 every time alas this is not the case. The java doc says join() "waits for this thread to die". I feel like the main thread should wait for t1 to finish then wait for t2 to finish. That's not what is happening. Thanks for the clarity!!
It does wait for the threads to die. But your two threads concurrently update a shared variable without any synchronization, so you're seeing race conditions and visibility issues.
For example:
counter = 1000
thread 1 reads counter : 1000
thread 2 reads counter : 1000
thread 1 increments and writes counter: 1001
thread 2 decrements and writes counter: 999
Since ++ and -- are not atomic operations, the above thread interlacing example loses an increment.
The easiest way to fix them is to use an AtomicInteger rather than an int. To understand the crux of the problem, you'd better read Java Concurrency in Practice, or at the very least the Java concurrency tutorial.

Java: Thread doesn't work

I'm trying to start a thread in a for-loop. This task should only wait for a second (Thread.sleep()), so every time the loop starts over again, a new thread is started and it should cause the code after the thread to wait until it is executed.
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
public class TimerClass implements Runnable{
#Override
public void run()
{
try{
Thread.sleep(1000);
System.out.println("Timer");
} catch(InterruptedException e)
{
}
}
}
As you can see, I implemented in both methods System.out.println() to check if they are actually executed. I get this:
29
28
27
26
...//25 - 3
2
1
0
Timer
Timer
Timer
//in all 29 times Timer
So it should be 29, Timer, 28, Timer and so on, but it isn't.
Does anyone know what's wrong with the code?
Thanks a lot.
Your main loop that is starting the thread is likely dominating the CPU, so it finishes doing its entire loop and only then do the threads get a chance to go.
In fact, given that all of your threads sleep for an entire second and you're only looping 29 times, you're guaranteed that your loop will finish (and print all of the numbers) before your threads do. Add a sleep to your main loop if you want the threads to print - remember, the main loop doesn't stop when you start a thread.
You can join a thread to the main thread so first your thread will finished then main thread
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
t1.join();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
Here is my code for spawning 2 threads or one thread depends on arrayList size but in my case this threads are doing much more complex tasks then just waiting 1 sec
for (int i = 0; i < array.size(); i += 2) {
Thread t1 = null;
Thread t2 = null;
if (i < array.size() - 1 && array.size() > 1) {
t1 = new Thread(array.get(i));
t2 = new Thread(array.get(i + 1));
t1.start();
t2.start();
}
else {
t2 = new Thread(array.get(i));
t2.start();
}
if (t1 != null)
t1.join();
if (t2 != null)
t2.join();
}
In my code I populate arrayList with Objects that Implements Runnable interface.
Even if you sleep the thread for 1ms, your results would be the same. If you can manage the thread to sleep for the time less than it takes to print the results, your result could be as expected. Here is my code where I have put the time of 1 ms but yet the results are the same.
public class MultiThreading implements Runnable
{
public void run()
{
try
{
Thread.sleep(1);
System.out.println("Timer");
}
catch(Exception e)
{
}
}
public static void main(String [] args)
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new MultiThreading());
t1.start();
String s = String.valueOf(i);
System.out.println(s);
}
}
}
If you comment out the Thread.sleep(1) method, then your results are as you expected.
Delay is much enough to let the for loop in count() to finish before is can print 'timer' from thread.
What is happening is that the thread you started starts executing and immediately goes to sleep. In the meantime, your loop just keeps running. As the whole point of threads is that they run asynchronously, I don't really understand why you think your main loop should be waiting for it to finish sleeping. The thread has started running and is now running independently of the main loop.
If you want to wait for the thread you just started to finish (in which case, you might as well use a method), then use one of the synchronisation primitives, i.e. Thread.wait().
What you actually want to do is block your main thread while another thread is running. Please don't use Thread#sleep statements, as these are unreliable in order to "make your application work". What you want to use instead is Thread#join. See dharr his code for an example.
Also, it's better to use Executors and ExecutorServices when creating threads or running async tasks.
Threads are interesting. Think of a virtual thread as a physical thread. There are many threads on the clothes you're wearing, all working at the same time to hold your shirt together. In virtual terms what Thread.start() does is start a thread on a different strand WHILE the following code continues to execute, (i.e. Two Threads work simultaneously like 2 runners run next to each other). Consider putting a break point right after Thread.start(). You'll understand.
For your desired effect, just put a Thread.sleep() in the main loop. This will cause an output of
29
Timer
28
Timer
// etc.
Hope this helped.
Jarod.
Another analogy to the threads in a shirt:
Think of threads as coworkers to your main programm (which is a thread itself). If you start a thread, you hand some work to this coworker. This coworker goes back to his office to work on this task. You also continue to do your task.
This is why the numbers will appear before the first thread/coworker will output anythig. You finished your task (handing out work to other coworkers) before he finished his.
If you want to give out some work and then wait for it to be finished, use t1.join() as suggested by others. But if you do this, it is senseless to create new Threads, because you don't (seem) to want to process something in parallel (with many coworkers) but in a specific order - you can just du it yourself.

Categories