У вас возникли трудности, потому что вы используете неправильный шаблон.
Ваш Task
s не должен возвращать следующее состояние. Для управления потоком вы должны использовать матрицу State
s. Таким образом, ваш поток не запутывается внутри задач, а State
остаются закрытыми для системы потока.
Если вы хотите, чтобы ваш Task
контролировал поток, они должны что-то вернуть (возможно, успех/отказ) повлиять на контроллер потока. Они не должны определить следующее состояние, они должны влияние следующее состояние.
Добавлено
Вот несколько надуманный пример того, что я имею в виду. Обратите внимание, что Task
s прикреплены к каждому State
, а поток управляется Map
, который просто удерживает каждый переход состояния.
Я предпринял попытку поднять итог, чтобы соответствовать вашим возвращающимся результатам, но я подозреваю, что это просто перекомплементивает вопросы, и как только вы охватите разделение потока из состояния, вы поймете, что я пытаюсь объяснить.
public class Test {
public void test() {
new Thread(new Engine()).start();
}
static final Map<State, State> flow = new HashMap<>();
static {
flow.put(State.Start, State.A);
flow.put(State.A, State.B);
flow.put(State.B, State.Finished);
}
public static class Engine implements Runnable {
State state = State.Start;
@Override
public void run() {
while (state != State.Finished) {
System.out.println("State: "+state);
// Perform all tasks of this state.
for (Task task : state.tasks) {
System.out.println("Task: "+task);
Result result = Result.Start;
// Keep performing until completed.
while (result != Result.Completed) {
System.out.println("Result: "+result);
result = result.perform(task);
}
System.out.println("Result: "+result);
}
// All tasks performed! Next state.
state = flow.get(state);
}
System.out.println("State: "+state);
}
}
enum State {
Start,
A(Task.One, Task.Two),
B(Task.Two),
Finished;
Iterable<Task> tasks;
State(Task... tasks) {
this.tasks = Arrays.asList(tasks);
}
}
enum Result {
Start {
@Override
Result perform(Task t) {
return t.initialise();
}
},
Executing {
@Override
Result perform(Task t) {
return t.execute();
}
},
Finalising {
@Override
Result perform(Task t) {
return t.finalise();
}
},
Completed {
@Override
Result perform(Task t) {
// Stop there.
return Completed;
}
};
abstract Result perform(Task t);
}
enum Task {
One {
@Override
Result initialise() {
return Result.Executing;
}
@Override
Result execute() {
return Result.Finalising;
}
@Override
Result finalise() {
return Result.Completed;
}
},
Two {
@Override
Result initialise() {
return Result.Executing;
}
@Override
Result execute() {
return Result.Finalising;
}
@Override
Result finalise() {
return Result.Completed;
}
};
abstract Result initialise();
abstract Result execute();
abstract Result finalise();
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
Добавлено
Упрощая, убрав ваше требование, чтобы контролировать поток через результаты методов задачи получаем:
public class Test {
public void test() {
new Thread(new Engine()).start();
}
static final Map<State, State> flow = new HashMap<>();
static {
flow.put(State.Start, State.A);
flow.put(State.A, State.B);
flow.put(State.B, State.Finished);
}
public static class Engine implements Runnable {
State state = State.Start;
@Override
public void run() {
while (state != State.Finished) {
System.out.println("State: "+state);
// Perform all tasks of this state.
for (Task task : state.tasks) {
System.out.println("Task: "+task);
task.initialise();
task.execute();
task.finalise();
}
// All tasks performed! Next state.
state = flow.get(state);
}
System.out.println("State: "+state);
}
}
enum State {
Start,
A(Task.One, Task.Two),
B(Task.Two),
Finished;
Iterable<Task> tasks;
State(Task... tasks) {
this.tasks = Arrays.asList(tasks);
}
}
enum Task {
One {
@Override
void execute() {
}
},
Two {
@Override
void execute() {
}
};
// Nothing by default.
void initialise() {
}
abstract void execute();
// Nothing by default.
void finalise() {
}
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
, который, как мне кажется, демонстрирует разделение контроль потока от выполнения задачи, с которой я пытался справиться.
Нет, вы не можете отметить некоторые константы перечисления public и некоторые частные пакеты. –
В этом случае, возможно, вы можете использовать старые java-перечисления, просто класс с некоторыми конечными статическими константами. – Marcelo
На самом деле вы ничего не можете отметить. Они «публичные», и все. –