1

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.

user3578062
  • 13
  • 2
  • 5

8 Answers8

7

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.

Evan Knowles
  • 7,426
  • 2
  • 37
  • 71
  • You can put it directly after `t1.start();` – Evan Knowles May 23 '14 at 12:20
  • 1
    or you could change your i to something beyond 10K. Well, obviously @EvanKnowles idea is better. – TheLostMind May 23 '14 at 12:21
  • 1
    "...you're guaranteed that your loop will finish...before your threads do." Ahem! You are _practically_ guaranteed, but not _actually_ guaranteed. That sort of thinking leads to the kind of bug that only surfaces once every few years, evades all testing, and eventually causes the rocket to explode. – Solomon Slow May 23 '14 at 13:24
  • True - I do hope this code doesn't end up in a rocket. – Evan Knowles May 23 '14 at 13:25
3

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.

dharr
  • 328
  • 1
  • 11
  • now it works that the number and timer are printed after each other, but the actual sense of all this was the jLabel6 to be refreshed. Now the gui just appears after i == 0. do you have any idea for that? – user3578062 May 23 '14 at 12:27
  • You need to investigate threads more deeply. Change your class TimerClass so it can access jLabel6. Now what is happening is thread executed its task then main method is setting text for jlabel – dharr May 23 '14 at 12:34
  • @dharr what about using t.wait() can it be used in this scenario if yes can you let us know that also – vikeng21 May 23 '14 at 12:34
  • I send you to that topic -> [wait vs sleep](http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep) It all depends on what do u want to achieve – dharr May 23 '14 at 12:37
2

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.

Lok
  • 131
  • 8
0

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

sudmong
  • 2,036
  • 13
  • 12
0

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

wds
  • 31,873
  • 11
  • 59
  • 84
0

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.

xaviert
  • 5,653
  • 6
  • 29
  • 31
0

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.

TheBrenny
  • 528
  • 3
  • 19
0

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.

Soana
  • 711
  • 7
  • 15