0

I want to execute two separate threads in strickly sequence, that is "A->B->A->B", who know how to do it?

I don't want any delay(such as sleep, yield) between the sequence.

Here is some code I writ but can't work:

    public void onClick_start_thread_a(View v) {
    logger.d("onClick_start_thread_a");
    Runnable r = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                synchronized (flag) {
                    try {
                        flag.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    logger.d("Thread A!");
                }
            }
        }
    };
    Thread t = new Thread(r);
    t.start();
}

public void onClick_start_thread_b(View v) {
    logger.d("onClick_start_thread_b");
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                synchronized (flag) {
                flag.notify();
                logger.d("Thread B!");
                }
            }
        }
    };
    Thread t = new Thread(r);
    t.start();
}

The onClick_start_thread_a and onClick_start_thread_b are triggered by two different buttons, after I click the buttons, the output is:

01-11 22:49:40.705: D/THING(25877): {Thread:Thread-619}[MainActivity:] Thread A!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-619}[MainActivity:] Thread A!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-619}[MainActivity:] Thread A!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-619}[MainActivity:] Thread A!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
01-11 22:49:40.705: D/THING(25877): {Thread:Thread-620}[MainActivity:] Thread B!
morgano
  • 17,210
  • 10
  • 45
  • 56
user991800
  • 385
  • 2
  • 5
  • 13
  • possible duplicate of [Java Thread Ping Pong example](http://stackoverflow.com/questions/12785238/java-thread-ping-pong-example) – Leo Aug 26 '14 at 03:50
  • it's not a duplicate in my mind, I want to use the object wait/notify – user991800 Aug 26 '14 at 06:57

3 Answers3

1
    public void onClick_start_thread_a(View v) {
    logger.d("onClick_start_thread_a");
    Runnable r = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                synchronized (flag) {
                    System.out.println("Thread A!");
                    flag.notifyAll();
                    try
                    {
                        flag.wait();
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    };
    Thread t = new Thread(r);
    t.start();
}

public void onClick_start_thread_b(View v) {
    logger.d("onClick_start_thread_b");
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                synchronized (flag) {
                    System.out.println("Thread B!");
                    flag.notifyAll();
                    try
                    {
                        flag.wait();
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    };
    Thread t = new Thread(r);
    t.start();
}
Terrence
  • 116
  • 7
  • I test it on my computer and it works well.What's your result? – Terrence Aug 26 '14 at 07:48
  • `01-12 11:13:07.211: I/System.out(30483): Thread A!` `01-12 11:13:07.211: I/System.out(30483): Thread A!` `01-12 11:13:07.211: I/System.out(30483): Thread B!` `01-12 11:13:07.211: I/System.out(30483): Thread B!` – user991800 Aug 26 '14 at 13:24
  • maybe the error come from the log---it may not output the log text immediately? – user991800 Aug 26 '14 at 13:34
  • I think I can confirm my suppose: After adding "Thread.sleep(10)" before "System.out.println(xxxx)" in each function, the output is correct. So it should be a trace issue. Thanks for your answer, it 's quite useful. – user991800 Aug 26 '14 at 13:45
0

What you probably want is some sort of semaphore and signaling mecahism.

Start Threads A and B
B - waits on semaphore
A - does stuff
A - when finished A signals B
A - waits on semaphore
B - does stuff
B - when finished B signals A
...... repeat until done

Have a look at the docs here

James Anderson
  • 27,109
  • 7
  • 50
  • 78
0

If it's a simple case like yours (only 2 threads), then I think you can get away with a simple boolean (AtomicBoolean in case of Java)

1) set boolean (let's call it decider) to false

2) start both threads

3) thread one will have:

while(true) {
  if(decider.get()) {
    // do stuff
    decider.set(false);
  }
}

The other one:

while(true) {
  if(!decider.get()) {
    // do stuff
    decider.set(true);
  }
}

That while(true) (or some other condition) seems a bit of an overhead so you could just add a single lock in both if statements instead (Lock#lock() will wait for the lock to be free)

If you want to generalize it to more threads you just need to substitute the boolean with something that can take more states. Each thread might have an ID (from 0 to N) and would enter the if only when invocationNr modulo nrOfThreads == ID.

Mateusz Dymczyk
  • 14,969
  • 10
  • 59
  • 94