2011-04-20 3 views
0

안녕하세요 모두
Java에서 멀티 스레딩에 문제가 있습니다. 이것은 나의 시나리오이다. 나는 LocalTime이라는 클래스를 가지고있다. 이 클래스는 시스템의 현재 시간을 알아야하며 getCurrentTime 인 메서드를 통해이 값을 Form에 반환합니다. 이것은이 클래스
Java의 멀티 스레딩

public class LocalTime implements Runnable { 

private String currentTime=null; 
Thread t; 
private long time; 
private long h; 
private long m; 
private long s; 
public LocalTime() { 
    t=new Thread(this,"current Time"); 
    t.start(); 

} 

public synchronized void run() { 

    try { 
     for(;;){ 
     Thread.sleep(1000); 
        time = System.currentTimeMillis()/1000; 
        h = (time/3600) % 24; 
        m = (time/60) % 60; 
        s = time % 60; 
        this.currentTime=h+":"+m+":"+s; 
     } 
    } catch (InterruptedException ex) { 
     Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 
public String getCurrentTime(){ 
    return this.currentTime; 
} 

} 

의 코드이며,이 기본 폼의 코드입니다 :

public MainForm1() { 
    initComponents(); 
    LocalTime l=new LocalTime(); 
    this.jLabel1.setText(l.getCurrentTime());//show the current time 
    //The rest of code 
} 


지금 내 큰 문제가하는 현재의 시스템 시간을 보여줍니다 jLabel1 텍스트입니다 1 초마다 업데이트되지 않습니다. 의 줄 앞에 (;;)을 삽입하면 jLabel1.setText (l.getCurrentTime())의 나머지 코드는 재사용 할 수 없습니다. 이 오류를 해결하려면 어떻게해야합니까? 이 가정들에 대한 해결책을 제안 해주십시오. MainForm1에 스레드를 실행할 수 있다는 것도 알고 있지만이 문제에 대한 해결책을 원합니다.

+0

가능한 복제본 http://stackoverflow.com/questions/5183318/improve-accuracy-of-my-timer-thread –

답변

3

문제는 방금 한 번만 읽는 것입니다. LocalTime을 쿼리하는 작업자 스레드를 시작하거나 시간 변경을 알리고 레이블 업데이트를 트리거하는 LocalTime에 수신기를 추가해야합니다.

부수적 인 표현 : 멋지게 형식화 된 표현을 얻으려면 을 SimpleDateFormat과 함께 사용하는 것이 좋습니다.

+2

작업자 스레드에서'setText'를 호출하면 안된다는 점에 유의하십시오. 따라서 이벤트 스택에 업데이트를 다시 대기시켜야하므로 Rom1이 제안하는 것처럼 Swing 타이머를 사용하는 것이 훨씬 쉽습니다. –

2

그런 종류의 작업에는 Timer을 사용하십시오 ... 왜 여분의 복잡성이 모두 필요합니까? 이 같은 것을보십시오 :

int delay = 1000; //milliseconds 
    ActionListener taskPerformer = new ActionListener() { 
    final LocalTime locTime = new LocalTime(); 
    public void actionPerformed(ActionEvent evt) { 
     jLabel1.setText(locTime.getCurrentTime()); 
    } 
    }; 
    new Timer(delay, taskPerformer).start(); 
+1

최근 Javadoc에 대한 링크를 업데이트했습니다. 1.4 년이 지났습니다. OP가 아마도 Swing에 처음 나온다면 여기에서 Swing 타이머를 사용하는 방법을 확장 할 수 있다고 생각하십니까? –

0

TimerTask를 만들고 타이머의 실행 방법에 의 setText를 호출합니다. 그런 다음 schedule 초마다 실행할 작업.

+1

EDT에서'setText'를 호출해야합니다. 스윙 타이머가 더 좋습니다. –

+0

@ Mark Peters - 맞아. OP는 이벤트 큐에 업데이트를 디스패치해야합니다. 이것은 Sun (현재 Oracle) 사이트에서 매우 명확하게 설명됩니다. http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html –

+0

네, 그게 더 나은 해결책이 될 것입니다. 나는 스윙에서 일한 적이 없으므로 스윙 타이머에 대해 몰랐다. 의견을 주셔서 감사합니다. 방금 thread.sleep()이 루프 안에서 사용되어 접근법을 수정하려고하는 방법을 살펴 보았습니다. – kunal

2

중요한 코드 조각을 포함하지 않는 한, 레이블을 두 번 이상 업데이트 할 수있는 방법이 없습니다.

사용자 정의 스레드가 매초마다 실행 중이고, 자신의 this.currentTime 필드를 업데이트합니다.

그러나 거기에 있었다으로 어떤 l, 그것은 단지 (this.jLabel1.setText(l.getCurrentTime())를 통해) 한 번 업데이트됩니다 (적어도 당신이 보여주고있다 코드의 빈약 한 금액) 라벨은 그 순간에서 시간 필드 입니다.

로컬 시간 스레드가 실행되기 때문에 마술로 나가서 레이블을 업데이트하지는 않습니다. 자신을 코딩하지 않으면 왜 마 법적으로 그렇게할까요? 그것에 대해 생각 해봐.

당신이해야 할 일은 스레드가 실행 방법 내에서 레이블 자체를 업데이트하도록하는 것입니다. 게다가 이것은 스윙 스레드 규칙 (및 이벤트 큐) 내에서 수행되어야합니다. 리팩터링을 통해 깨끗한 코드를 얻는 방법은 다른 스레드에 대한 주제입니다.

// java pseudocode 

public void run() { 

    Runnable labelUpdater = new Runnable() 
    { 
     public void run() 
     { 
     someForm.jLabel1.setText(yourUpdatedTimeFormattedAsStringOrWhatever); 
     } 
    } 
    try { 
     for(;;){ 
      Thread.sleep(1000); 
      // will cause label update to occur in the awt event queue 
      SwingUtils.invokeLater(labelUpdater); 
     } 
    } catch (InterruptedException ex) { 
     Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

일부 노트 :

  1. 당신은 당신의 run() 메소드의 특정 인스턴스에서 synchronized 키워드가 필요하지 않습니다.
  2. java.util.Calendar 및 java.util.Format을 사용하여 현재 시간의 문자열 표현을 가져옵니다. 모든 문자열 연결과 함께 System.currentTimeMillis()의 출력을 나눕니다. 자바 API를 보면서 이미 당신을 위해 무엇이 있는지 보셨습니까 ???????? 당신이 읽을

재료 : http://download.oracle.com/javase/tutorial/essential/concurrency/

0

이 유 misssing되는 단 한 가지가 스윙에

동시성 http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#event_dispatching

동시성 (자바 튜토리얼)을 업데이트하는 것입니다 각 초 후에 레이블. 시스템 날짜를 사용하여 시간을 계산하는 스레드가 정상적으로 작동합니다. 할 수있는 일은 초당 이벤트를 발생시키고 이벤트 리스너의 텍스트 필드 값을 변경하는 것입니다.