user10017436
user10017436

Reputation:

Switching to main thread

I'm wondering wether or not it is possible to somehow move from a secondary thread I created to my main thread. The secondary thread runs repeatedly, however, the API that I use doesn't really like that I do certain things in this secondary thread, so I would like to move those things into my main thread (that can't have an infinite loop):

// this is the main thread
void Main() {
    threadB();
}

// gets called from the main thread but creates its own
void threadB() {
    Timer t = new Timer();
    TimerTask tt = new TimerTask() {
        @Override
        public void run() {
            doSomeStuff();
        }
    };
    t.schedule(tt, 10000, 1000);
}

void doSomeStuff() {
    // this function will now be executed in threadB
    // the API hates what happens in this function but ONLY if its in threadB
    // so can i somehow get threadB to make threadA(Main) call this function?
}

Thanks in advance! I hope I explained this well enough. BTW there is no getting around creating threadB, there will always be one and it will always have to do the same thing

Upvotes: 2

Views: 708

Answers (1)

Daniele
Daniele

Reputation: 2837

You have a (main) worker thread, and this thread receives tasks (Runnables) from the timer thread, and executes them.

These two threads (timer and worker) interact via a queue; the timer pushes tasks, and the worker polls the queue and runs them. If no tasks are sent, then the main thread waits on the task queue.

The solution below is based on a queue; another possibility (more "low level") would be to use Object.wait() and notify() on a shared object to send signals between the threads.


In code,

package stackOv;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Threads {

  public static void main(String[] args) {
    Threads o = new Threads();
    System.out.println("main thread is: " + Thread.currentThread().getName());
    o.mainThreadRun();
  }

  // the timer will push tasks to the queue
  // the main thread will execute tasks from this queue
  // (the main thread should be the only worker!)
  BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();

  // the main thread executes this
  void mainThreadRun() {
    // the main thread starts the timer
    threadB();

    while (!Thread.interrupted()) {
      try {
        // waits for a task to become available
        // if the queue is empty, waits until a task is submitted
        Runnable task = tasks.take();
        // execute the task
        task.run();
      } catch (InterruptedException e) {
        System.out.println("interrupted");
        return;
      }
    }
  }

  // executed in the main thread; spawns a timer
  void threadB() {
    Timer t = new Timer();
    TimerTask tt = new TimerTask() {
      @Override
      public void run() {
        try {
          tasks.put(new Runnable() {
            @Override
            public void run() {
              doSomeStuff();
            }
          });
        } catch (InterruptedException e) {
          System.out.println("error");
        }
      }
    };
    t.schedule(tt, 1000, 1000);
  }

  void doSomeStuff() {
    System.out.println("doSomeStuff: executing from thread=" + Thread.currentThread().getName());
  }
}

Upvotes: 1

Related Questions