2014-01-28 6 views
0

HotKey 조합에서 뭔가를하는 Java 응용 프로그램을 만들고 있습니다. HotKey 입력이 닫힐 때까지 기다리는 무한 while 루프가 있지만 앱 CPU 시간이 많이 소요됩니다.Java에서 다른 스레드로부터의 입력으로 하나의 스레드가 무한 대기합니다.

다음은 내 코드는 가장 간단한 방법으로 보이는 방법은 다음과 같습니다.

static boolean isOpen = true; 
void main() 
{ 
    .... 
    add SomeHotKeyListener(); 
    .... 
    while(isOpen) 
    { } 
    releaseResources(); 
} 

void onHotKey(int hotKeyIdentifier) 
{ 
    if(hotKeyIdentifier == something) 
     do something; 
    if(hotKeyIdentifier == something) 
     isOpen = false; 
} 

내가 이것을 달성하기 위해 멀티 스레딩 접근 방식이 필요하거나 다른 사람이있는 경우 더 나은 뭔가에 맞게

답변

1

당신을 추천합니다 자바에서 synchronized 키워드에 대해 읽어보십시오. 단지 Google it 일 뿐이므로 많은 예제와 tutorials을 찾아야합니다. 루프는 시스템 자원의 꽤 많이 소비 할 수

static boolean isOpen = true; 
static Object lock = new Object(); 
void main() 
{ 
    .... 
    add SomeHotKeyListener(); 
    .... 
    synchronized(lock) 
    { 
     while(isOpen) 
     { 
      try { 
       lock.wait() 
      } catch(InterruptedException e) { 
      } 
     } 
    } 
    releaseResources(); 
} 

void onHotKey(int hotKeyIdentifier) 
{ 
    if(hotKeyIdentifier == something) 
     do something; 
    if(hotKeyIdentifier == something) 
    { 
     synchronized(lock) 
     { 
      isOpen = false; 
      lock.notify(); 
     } 
    } 
} 
+0

답장을 보내 주셔서 감사합니다. 필요한 것이 었습니다. – SnapADragon

+0

문제는 없습니다. 내가 잊어 버린 한 가지는 (그리고 그의 답변에서 언급 된 zencv) isOpen' 휘발성을 만드는 것입니다. 이것은 [두 가지 스레드가 같은 변수를 참조 할 때 동일한 메모리에 액세스 하는지를 확인하는 데 매우 중요합니다. http://www.javamex.com/tutorials/synchronization_volatile.shtml). – PaF

+0

동기화 된 블록에서 대기하고 통보하는 이전 솔루션이 필요하기 때문에이 경우 휘발성 변수를 사용해야하는 이유는 무엇입니까? – SnapADragon

0

무한 동안 :

은 당신의 사건을 해결해야한다. 대기 및 알림을 사용하는 것이 좋습니다. 또한 부울 volatile을 선언해야합니다. 그렇지 않으면 한 스레드가 변경 한 내용이 다른 스레드에 의해 선택된다는 보장이 없습니다. 다음은 별도의 스레드에서 작업을 수행하고 사용자 입력 (이 경우 입력)을 기반으로 호출 스레드가 중단 할 때까지 수행하는 예제입니다. Oracle의 예제도 참조하십시오. here

import java.util.Scanner; 

public class WaitTest implements Runnable { 

private volatile boolean shutdown = false; 

public static void main(String[] args) { 

    WaitTest w = new WaitTest(); 

    new Thread(w).start(); 

    System.out.println("Press any key to interrupt"); 
    Scanner sc = new Scanner(System.in); 
    sc.nextLine(); 

    w.triggerShutDown(); 
} 

@Override 
public void run() { 
    while (!shutdown) { 
     synchronized (this) { 
      try { 
       System.out.println("doing some silly things"); 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    System.out.println("Server shutdown successfully"); 
} 

public synchronized void triggerShutDown() { 
    this.shutdown = true; 
    notify(); 
} 
} 
+0

필자는 Oracle 문서에서 다음 줄을 읽습니다. "동기화 된 메서드가 종료되면 동일한 개체에 대한 동기화 된 메서드의 후속 호출과 함께 자동적으로 happen-before 관계를 설정합니다. ** 이렇게하면 개체의 상태 모든 스레드 **에서 볼 수 있습니다. ". [here] (http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html) 소스를 찾으십시오. 다른 스레드가 아닌 동일한 스레드 사용을 위해 volatile 변수를 사용해야합니까? – SnapADragon

+0

이 경우에는 'volatile'키워드가 실제로 필요합니다. 이유는 '셧다운'이 다른 방어 메커니즘이없는 두 개의 스레드에서 동시에 액세스 될 수있는 경우가 있기 때문입니다. 이것은'run()'함수의 첫 번째 행에서 발생합니다. 'shutdown '에 대한 모든 액세스가 동기화 된 코드 내에 있다면, 이것은 필요하지 않았을 것입니다. – PaF

+0

내 대답은 동기화 된 블록 내에'while (! shutdown)'을 넣어서 해결했다는 것을 기억하십시오. 내 솔루션은 캡슐화 함수'main()'이 한 번만 호출되기를 기대할 때 더 좋습니다. zencv의 솔루션은 캡슐화 함수'run()'이 두 번 이상 호출 될 것으로 기대할 때 더 좋습니다 (후속 호출에서는'shutdown'을 'true'로 즉시 식별하므로 동기화 된 코드를 전혀 입력 할 필요가 없습니다). 동기 코드를 입력하면 비용이 발생한다는 것을 기억하십시오. – PaF