user3578062
user3578062

Reputation: 13

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.

Upvotes: 1

Views: 3840

Answers (8)

Lok
Lok

Reputation: 131

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.

Upvotes: 2

Soana
Soana

Reputation: 711

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.

Upvotes: 0

dharr
dharr

Reputation: 328

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.

Upvotes: 3

TheBrenny
TheBrenny

Reputation: 527

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.

Upvotes: 0

xaviert
xaviert

Reputation: 5942

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.

Upvotes: 0

wds
wds

Reputation: 32303

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().

Upvotes: 0

sudmong
sudmong

Reputation: 2036

Delay is much enough to let the for loop in count() to finish before is can print 'timer' from thread.

Upvotes: 0

Evan Knowles
Evan Knowles

Reputation: 7511

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.

Upvotes: 7

Related Questions