가변적 인 시간이 걸리는 복잡한 계산이 있습니다. 일부 입력 값을 사용하면 1 초에 1000 단계를 수행 할 수 있습니다. 다른 입력 값을 사용하면 몇 초가 걸립니다.GUI가 계산 시간이 오래 걸리고 전체 프로세스가 느려짐
완전히 정확하므로 사용자에게 진행 상황을 알리고 싶습니다. 문제는 이전의 경우 GUI를 업데이트하는 것이 실제 계산보다 오래 걸린다는 것입니다. 따라서 완료된 후 대기열에 GUI 업데이트 이벤트가 약 10 초 (이 경우 전체 계산의 실행 시간을 3 배로 늘림) .
그게 일반적인 문제라고 생각, 그래서 다소 틀에 얽매이지 예에 고장 :
public class QueueTest {
static final int STEPS = 30;
public static void main(String[] args) {
final Gui gui = // ...
final Display display = Display.getDefault();
final Thread thread = new Thread(() -> {
for (int i = 0; i < STEPS; i++) {
final int step = i; // calculate something etc.
gui.updateLater(display, step);
}
System.out.println("Finished calculation.");
});
thread.start();
while (true) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
interface Gui {
default void updateLater(Display display, int step) {
display.asyncExec(() -> update(step));
}
default void update(int step) {
System.out.println("Update " + (step + 1) + "/" + STEPS);
if (step == STEPS - 1) {
System.out.println("Finished GUI.");
}
}
}
}
(추가 Thread
은 단계를 "계산"과 진행 상황을 표시하는 GUI로 전송 .)
그럼 Gui
의 일부 구현을 살펴 보자 :
static class NoGui implements Gui {
@Override
public void update(int step) {
if (step == STEPS - 1) {
System.out.println("Finished GUI.");
}
}
}
이 예제는 GUI가 완료 될 때만 인쇄합니다. 결과는 거의 동시에 인쇄되는 두 줄입니다.
Finished calculation.
Finished GUI.
매우 합리적입니다. GUI 이벤트는 빨리 완료됩니다. 이제 느린을 만들어 보자 :
는static class SlowGui implements Gui {
@Override
public void update(int step) {
try {
Thread.sleep(100);
Gui.super.update(step);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
이 계산의 마지막 3 초 떨어져 GUI로, 다음과 같은 것을 인쇄 : 나는 우리의 응용 프로그램에서보고 있어요 무엇
Finished calculation.
Update 1/30
Update 2/30
Update 3/30
...
Update 30/30
Finished GUI.
. 계산이 완료되었지만 GUI가 너무 느리고 계산이 이미 완료된 후 이벤트 대기열을 실행해야합니다.
나는이 동작을 최적화하려는이 같은 내놓았다 :
Finished calculation.
Update 1/30
Update 30/30
Finished GUI.
이 구현은 단지 사이 등의 이벤트를 무시 :
static class IgnorantGui extends SlowGui {
private boolean inProgress;
private Integer nextStep;
@Override
public void updateLater(Display display, int step) {
if (this.inProgress) {
this.nextStep = Integer.valueOf(step);
} else {
this.inProgress = true;
super.updateLater(display, step);
}
}
@Override
public void update(int step) {
try {
Integer currentStep = Integer.valueOf(step);
do {
super.update(currentStep.intValue());
currentStep = this.nextStep;
this.nextStep = null;
} while (currentStep != null);
} finally {
this.inProgress = false;
}
}
}
출력은 다음 네 줄입니다 훨씬 빠릅니다. 이것은 내 문제에 대한 유효한 해결책이다.
이 전체적인 사용 사례가 일반적 일 수 있다고 생각합니다. 아마도 더 좋은 해결책이 될 것입니다. 또는이를 처리 할 수있는 표준 Java API도 있습니다. (아마도 SWT/Eclipse Framework API 일 것입니다.)
그래서 ... 계산보다 업데이트하는 데 시간이 오래 걸리므로 응용 프로그램이 느려지는 GUI를 처리하는 방법은 무엇입니까?
GUI 업데이트를 처리하기 위해'invokeLater()'를 사용한다고 가정합니다. – Kayaman
@Kayaman'invokeLater()'가 스윙입니다, 그렇죠? 우리는 SWT를 사용하고 있습니다. –
내 기억이 올바르게 작동한다면 스윙은 처리량을 향상시키기 위해 이벤트를 병합 할 수 있습니다. 나는 SWT가 비슷한 것을 가지고 있다고 생각한다. 귀하의 예는 너무 추상적입니다. 사용중인 실제 기술을 사용하여 [MCVE] (https://stackoverflow.com/help/mcve)를 만들고이를 해결해보십시오. – Kayaman