0

I have two methods in which I want to be able to run concurrently.

public void bar(){
    //Do some stuff which has a result
    //If result is true, then stop foo().
}

public void foo()
{
    for (int x = 0; x <= 100; ++x)
    {
        //Do some stuff...
        //Execute bar, but don't wait for it to finish before jumping to next iteration.
    }
}

The way I understand it, when a method is called, it gets put onto the stack, and then when the method finishes it returns from the stack and then the program will continue to execute from where the method was called.

So if foo() calls bar() during the loop it will wait until bar() returns before continuing the loop.

However, what I want to happen is that when foo executes bar, it doesn't wait until bar has finished executing before it continues its iteration; it just notifies that bar() should run and then continues looping.

Similar to how run in a Thread will run the method and then return it, but start will start the run method in a new thread, and the start method returns immediately, allowing the next line of code to run.

Additionally, each time bar() is run, depending on the result, I want it to interrupt foo() regardless of which line of foo() is currently being executed. I do not want to check the result of bar() within the foo() method, but I want functionality such that while foo() is executing it is interrupted by bar()'s execution.

Hopefully, to make this simpler to understand: let's say I have two people doing tasks A and B. A is foo, and B is bar.

A is going to do his task 100 times, but after each time he does a task he tells B to do his respective task (calling bar() at the end of each iteration), and then continues onto the next of his tasks.

The time it takes B to do his task is shorter than the time it takes A to do his task, so when B finishes his task, A will still be executing his task, and depending on the result of B's task, he may tell A to halt the execution of his task.

NotAPro
  • 136
  • 2
  • 17

2 Answers2

1

however I don't want to create a new Thread every time to do a new iteration of bar().

You can implement Thread Pool which will juggle threads for you, so your program won't keep spawning new threads for B tasks - it will grab worker threads instead. Worth considering

BTW: How to stop a thread from another thread? should give you a hint on how to manage thread interruptions

EDIT: You can get active Threads references by name.

Thread getThreadByName(String name) {
    // Get current Thread Group
    ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
    ThreadGroup parentThreadGroup;
    while ((parentThreadGroup = threadGroup.getParent()) != null) {
        threadGroup = parentThreadGroup;
    }
    // List all active Threads
    final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    int nAllocated = threadMXBean.getThreadCount();
    int n = 0;
    Thread[] threads;
    do {
        nAllocated *= 2;
        threads = new Thread[nAllocated];
        n = threadGroup.enumerate(threads, true);
    } while (n == nAllocated);
    threads = Arrays.copyOf(threads, n);
    // Get Thread by name
    for (Thread thread : threads) {
        System.out.println(thread.getName());
        if (thread.getName().equals(name)) {
            return thread;
        }
    }
    return null;
}

And interrupt your running Thread from anywhere you want. Keep in mind that this is extremely gimmicky solution, and I would advise you to re-think your concurrent architecture. There are many good solutions in this post - give them a try.

void foo() {
    Thread fooThread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    bar(); // Spawns barThread, but continues execution
                    Thread.sleep(2000); // foo has to return after bar, else NullPointerException is thrown
                } catch (InterruptedException e) {
                    //handle interruption
                }
            }
        }
    }, "fooThread"); // here im assigning name to fooThread
    fooThread.start();
}

void bar() {
    Thread barThread = new Thread(new Runnable() {
        @Override
        public void run() {
            // do something that interrupts foo()
            getThreadByName("fooThread").interrupt();
        }
    });

    barThread.start();
}
vyrwu
  • 31
  • 3
  • I know I can use a flag to check whether to stop execution or not, but to get the desired functionality I need I would have to check the flag after each line of code which isn't practical. I want kind of like an ActionListener that listens for when bar() tells foo() to stop. – NotAPro Mar 11 '18 at 16:10
0

Im not quite sure what exactly you want to do. But it sounds like your problem can be solved with a queue.

queue = Queue(max_size=n)

thread_1:
    while True:
        x = foo()
        queue.put(x)

thread_2:
    while True:
        x = queue.get()
        doSomething(x)
A.Bau
  • 82
  • 1
  • 10
  • It’s (pythonlike) pseudo code. I only wanted to explain the concept. Not the specific implementation – A.Bau Mar 11 '18 at 20:13