Я думаю, здесь самый простой и дружественный к процессору способ добиться этого -
public void run() {
while(true) {
synchronized(foo) {
while(!invokeMyFunction) {
foo.wait();
}
}
MyFunction();
invokeMyFunction = false;
}
}
Приведенный выше код работает в своем собственном потоке. Другой поток может сделать это, чтобы первый поток запустил MyFunction ():
invokeMyFunction = true;
foo.notifyAll();
Обратите внимание, что
a) Вы не можете сделать invokeMyFunction логическим значением и синхронизировать его, потому что во всем Java есть только два логических значения :)
б) Если invokeMyFunction установлена n раз, она все равно может выполняться меньше раз, если invokeMyFunction установлена в значение true, но не ложно.
c) Использование BlockingQueue может быть проще и позволит потоку 1 запускать произвольные функции:
while(true) {
Runnable next = queue.take();
next.run()
}
И другой поток скажет ему запустить MyFunction так:
queue.put(new Runnable() {
void run() {
MyFunction();
}
});
Мне кажется это проще :) Кроме того, если вы хотите, чтобы n потоков запускало все, что поступает через очередь, вам просто нужно создать n потоков, которые прослушивают очередь. Или вы можете узнать, как использовать пулы потоков: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
Примечание:
queue.put () блокируется до тех пор, пока в BlockingQueue не будет доступно новое пространство, т.е. оно блокируется, если заполнено. Просмотрите документы по реализации используемой вами реализации BlockingQueue, чтобы узнать, имеет ли ваша очередь ограничение. В любом случае, убедитесь, что вы не добавляете больше элементов для работы, чем можете обрабатывать слишком долго.