Arjun Patel
Arjun Patel

Reputation: 353

Java - Println is not in order

I have multiple threads printing data. All the data does print; however, they are not in order. Meaning Thread 2 starts printing while Thread 1 is not done yet, which causes inconsistency. How do I guarantee consistency ? Meaning Thread 2 can print once Thread 1 is done.

Upvotes: 1

Views: 379

Answers (8)

Crollster
Crollster

Reputation: 2771

From your comments, you are looking to achieve 1 1 1 1 2 2 2 2 so what you'd need to do is actually wait for Thread1 to complete, then start Thread2, like this:

Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();

thread1.start();

thread1.join(); // This waits for Thread1 to finish before starting Thread2
thread2.start();

however, if you want to have both threads start, but have Thread2 wait part way through its processing, while waiting for Thread1 to complete - this can be done with a few techniques - one in particular comes to mind - using Semaphore.

Example:

Ok, firstly define your thread constructors to accept a Semaphore, thus:

// Thread2 would be identical wrt the semaphore
public Thread1(Semaphore semaphore) throws InterruptedException
{
  this.semaphore = semaphore; // store semaphore locally
  semaphore.acquire(2);
}

Thread1's run method would look like this:

public void run()
{
  // .... processing...

  // ... print stuff
  System.out.println("1 1 1 1");
  semaphore.release(); // release 1 permit, allowing thread2 to continue

  // ... more processing

  semaphore.release(); // release last permit.
}

Thread2's run method would look something akin to this:

public void run()
{
  int permits = 2;
  try
  {
    // .... processing...

    semaphore.acquire(1); // acquire one more permit (will block until Thread1 releases one)
    permits++;

    // ... print stuff
    System.out.println("2 2 2 2");

    // ... more processing      
  }
  catch (InterruptedException ie)
  {
    // interrupted
  }

  semaphore.release(permits); // release permits.
}

Now, setting up the threads would be done like this:

try
{
  Semaphore semaphore = new Semaphore(4); // 4 permit semaphore

  Thread1 thread1 = new Thread1(semaphore);
  Thread2 thread2 = new Thread2(semaphore);

  thread1.start();
  thread2.start();

  semaphore.acquire(4);
}
catch (InterruptedException ie)
{
  // interrupt logic...
}

Upvotes: 0

Brian Roach
Brian Roach

Reputation: 76898

You can not randomly print from multiple threads and expect any order.

If you need output in an ordered fashion then you're going to have to either synchronize the threads (thus defeating the purpose of having multiple threads) or have the threads pass back the information to output back to the main thread so it can handle ordering and outputting it.

Edit: Because I'm bored.

If you're trying to parallelize some work via threads then output the results, you need to have the threads communicate the product of their work back to the main thread and have it do the output. One approach to this is to use queues (this is simple example that relies on the thread order - you may need to get all the results and correlate/sort/etc):

public class Worker implements Runnable
{

    private ConcurrentLinkedQueue<Integer> outputQueue;

    public Worker(ConcurrentLinkedQueue<Integer> outputQueue)
    {
        this.outputQueue = outputQueue;
    }

    @Override
    public void run()
    {

       // Do whatever it is you're doing
       ...
       // place result on queue
       outputQueue.add(result);

    }

} 

public class Main
{

    static void main(String[] args)
    {

        ArrayList<ConcurrentLinkedQueue<Integer>> myQueues =
            new ArrayList<ConcurrentLinkedQueue<Integer>>();

        Thread[] myThreads = new Thread[numThreads];

        // Create queue, create thread with Worker(queue),  
        // start thread
        for (int i = 0; i < numThreads; i++)
        {
            ConcurrentLinkedQueue<Integer> queue =
                new ConcurrentLinkedQueue<Integer>();

            myQueues.add(queue);           

            myThreads[i] = new Thread(new Worker(queue)).start();

        }

        // Wait for all threads to finish, print their results
        for (int i = 0; i < numThreads; i++)
        {
            join(myThreads[i]);

            // Get the queue for the thread we just joined, 
            // pull off each result and output
            Integer j;
            while ((j = myQueues.get(i).poll()) != null)
            {
                System.out.println(j);
            }

        }
    }
}

This is off the top of my head, but that's the general approach

Upvotes: -1

dMb
dMb

Reputation: 9337

So, here's what you want to do (pseudo-code):

String results[2];

Thread1 thread1 = new Thread1() {
   public void run() {
      // do stuff; collect output
      results[0] = output
   }
};

Thread2 thread1 = new Thread1() {
   public void run() {
      // do stuff; collect output
      results[1] = output
   }
};

thread1.start();
thread2.start();

thread1.join();
thread2.join();

print result[0];
print result[1];

There are better ways of doing above using classes from java.util.concurrent, but this should give you an idea

Upvotes: 1

John Haager
John Haager

Reputation: 2115

If you want the code executed by Thread 1 to finish before running Thread 2, then you don't want threads. You might want to take a look at Java's ExecutorService. Specifically, Executors. newSingleThreadExecutor(). This will allow you to schedule tasks to be run in another thread, but insure that they are run sequentially.

Upvotes: 1

madth3
madth3

Reputation: 7344

You'd have to save Thread 2 output and print it until Thread 1 is one. Executing them in order as suggested would work too but then, why have Thread's?

Upvotes: 0

Vinit
Vinit

Reputation: 1825

We cannot calculate when a thread is going to run and complete the execution. It completely depends on the CPU. What you can do is have a flag variable at the end of first thread being updated to a value and check for that value before second thread executes.

Upvotes: 0

DanZimm
DanZimm

Reputation: 2568

Once the run method is done in thread one have it call something in thread two to let it know that it can print

Upvotes: 0

Tushar Chutani
Tushar Chutani

Reputation: 1560

this is how threads work.. if you start two thread it will go something like this 1 2 1 2 1 2 1 2

Upvotes: 0

Related Questions