Временно приостановить метод до следующего вызова
Можно ли создать метод, который может временно приостановить себя, "вернувшись", а затем возобновив его при повторном вызове? Он должен действовать так, как если бы он никогда не возвращался (т.е. сохранить все свои переменные, продолжить выполнение следующей строки и т. Д.).
public static void main(String args) {
method(); //should start method
//do stuff ONLY AFTER method() RETURNS
method(); //should continue method at same place as it ended
//do more stuff ONLY AFTER method() RETURNS
}
private static void method() {
while(true) {
//do stuff
return;
//do different stuff
return;
//do a third thing
return;
//then start all over
}
}
Я видел несколько вопросов о Stackru, которые похожи, но ни один из ответов не казался достаточным или объяснительным.
5 ответов
То, что вы ищете, похоже на оператор возврата C#: http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx
Насколько я знаю, подобной конструкции для Java не существует. Если вы действительно в отчаянии и не стесняетесь тяжелых манипуляций с байт-кодом, вы можете получить что-то свое:
Сначала создайте класс с помощью статического метода yieldReturn(). Затем вы можете найти во всех своих классах вызовы этого метода и выполнить модификацию в соответствии с http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx
Я думаю, что вы подходите к проблеме неправильно, но если вы настаиваете, вы можете передать состояние как параметры методу или поместить метод в другой класс и сохранить состояние как переменные экземпляра.
Поскольку он помечен как "miltithreading", я полагаю, что "классический" способ состоит в том, чтобы обрезать 'method()', сделать его бесконечным циклом и вместо call/return использовать wait/notify, или condvars, или двоичный семафор обменять поток "токен".
Я не видел эффективной реализации продолжения в Java, но есть другой подход, который может помочь вам.
Актеры (например, Akka) могут использоваться для реализации конечных автоматов, особенно потому, что они "переключают контекст" и "становятся" другим состоянием.
Фактически каждый метод будет манипулировать состоянием, и перед его завершением субъект переключится в это расширенное состояние.
Я нахожу подход достаточно легким по сравнению с продолжениями, которые могут быть несколько загадочными.
Вы можете подражать корутину так:
class Coruntine extends Thread {
Semaphore in = new Semaphore(0);
Semaphore out = new Semaphore(0);
boolean started=false;
public Coruntine() {
super.setDaemon(true);
}
public void method() {
if (started) {
in.release();
} else {
started=true;
start();
}
try {
out.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void _return() {
out.release();
try {
in.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
System.out.println("do stuff 1");
_return(); // like return
System.out.println("do stuff 2");
_return();
System.out.println("do stuff 3");
_return();
// then start all over
}
}
}
public static void main(String[] args) {
Coruntine c = new Coruntine();
c.method(); // should start method
System.out.println("do stuff AFTER method() RETURNS 1");
c.method(); // should continue method at same place as it ended
System.out.println("do stuff AFTER method() RETURNS 2");
c.method(); // should continue method at same place as it ended
System.out.println("do stuff AFTER method() RETURNS 3");
c.method(); // should continue method at same place as it ended
System.out.println("do stuff AFTER method() RETURNS 4");
}
если method()
должен возвращать значение и / или принимать параметры, использовать блокирующие очереди вместо семафоров.