2013-03-11 2 views
4

작업 - 하루 중 특정 시간에 전구를 켜거나 끕니다. 아래 주어진 정보에 따라 코드를 수정하는 방법을 알아야합니다. 타이머 클래스를 정확하게 사용하고 있는지, 즉, 제 코드가 올바른지 알고 싶습니다. 코드가 작동하지만 나중에 문제가 발생할 수있는 잘못된 디자인 일 수 있습니다. 나는 그런 일이 일어나기를 원하지 않는다.Java 타이머 코드를 수정해야합니다.

출력 (이 내가 정말 원하는 출력되지 않습니다 :()입니다 -

This is the main program 
Current time is - xxx 
Future time is - xxx+5sec 
Future time is - xxx+10sec 
Main program ends 
Bulb B1 is OFF 

원하는 출력 -? 내가

원하는 것을 얻을 수 아래의 코드를 수정하려면 어떻게

This is the main program 
Current time is - xxx 
Future time is - xxx+5sec 
Future time is - xxx+10sec 
Bulb B1 is ON //first on 
Bulb B1 is OFF //then off 
Main program ends//This should always be in the end. 

Bulb 클래스

class Bulb { 

private boolean state = false;//On or off 
private String name; 

Bulb(String name){ 

    this.name = name; 

} 

public void setState(boolean state){ 

    this.state = state; 
    if(this.state == true){ 

     System.out.println("Bulb " + name + " is ON"); 

    }else{ 

     System.out.println("Bulb " + name + " is OFF"); 

    } 

} 


public boolean getState(){ 
    return this.state; 

} 


} 

import java.util.*; 

class BulbJob extends TimerTask{ 

private Bulb bulbToHandle; 
private boolean setBulbStateEqualTo; 

BulbJob(Bulb toHandle){ 

    this.bulbToHandle = toHandle; 

} 


//NOTE: Must be called before run(), otherwise default value is used 
public void setBulbStateEqualTo(boolean setBulbStateEqualTo){ 

    this.setBulbStateEqualTo = setBulbStateEqualTo; 

} 


//NOTE: call run() only before calling above method 
public void run(){ 

    this.bulbToHandle.setState(setBulbStateEqualTo);//Set on or off 

} 

} 

BulbScheduler 클래스입니다

BulbJob 클래스 - 전구를 켜거나 끌 수있다이 일정.

import java.util.*; 

@SuppressWarnings("deprecation") 
class BulbScheduler { 

public static void main(String args[]) throws InterruptedException{ 

    System.out.println("This is the main program"); 

    Timer time = new Timer(); 
    Bulb b1 = new Bulb("B1"); 
    BulbJob bj = new BulbJob(b1); 

    bj.setBulbStateEqualTo(true);//Task - Turn bulb on at time = afterCurrent 

    Date current = new Date();//Get current time and execute job ten seconds after this time 
    Date afterCurrent = (Date) current.clone(); 

    System.out.println("Current time is - " + current); 

    int currentSecs = current.getSeconds(); 
    int offset = 5;//number of seconds 

    afterCurrent.setSeconds(currentSecs + offset); 
    System.out.println("Future time is - " + afterCurrent); 

    time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent 

    //Now turn the bulb off at new time = newest afterTime 
    afterCurrent.setSeconds(currentSecs + 2 * offset); 
    System.out.println("Future time is - " + afterCurrent); 

    bj.setBulbStateEqualTo(false);//Task - Now turn the bulb off at time = afterCurrent 

    System.out.println("Main program ends"); 

} 

} 
+0

+1 일반 스레드의'sleep()'보다 'TimerTask'를 선택하십시오. – asgs

+0

@asgs - 모든 프로그램이 실행 된 후에 만 ​​"주 프로그램 종료"를 수행하려면 어떻게해야합니까? – Time

+1

주 스레드가 당신의 잡에 의존하지 않기 때문에 TimerTask가 완료되기를 기다리기 위해'Thread'의'join()'메소드를 사용할 수 있도록 재 설계해야 할 것 같습니다. – asgs

답변

2

이 섹션 :

time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent 

//Now turn the bulb off at new time = newest afterTime 
afterCurrent.setSeconds(currentSecs + 2 * offset); 

만 일정을 하나의 작업. 두 번 예약해야하는 경우 명시 적으로 수행하십시오.

time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent 

//Now turn the bulb off at new time = newest afterTime 
afterCurrent.setSeconds(currentSecs + 2 * offset); 
time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent 

또한. 이 라인 :

bj.setBulbStateEqualTo(false); 

는 메인 스레드에서 실행되는, 그래서 전에 모두 작업 것이다. 두 작업간에 실행되도록 명령문을 예약해야합니다.

+1

또한이 작업은 currentTime + 5 초 그러면 같은 전구를 currentTime + 10 초에 끈다. 전구를 끄기 위해 새로운 전구 또는 타이머를 만들어야합니까? – Time

+1

3 가지 작업을 만듭니다 : turnBulbOn, turnBulbOff, ExitProgram. 당신은 하나의 타이머 만 필요합니다. – assylias

+0

당신은 사용자 정의 메시지를 사용하여 프로그램을 별도의 TimerTask로 끝내는 것이 최선의 방법입니다 : – asgs

0

코드는 고정되어 있지만,이 버전은 결국 주요 종료 할 수 없습니다 - 당신은 시간을 정확하게 설정되지

import java.util.*; 

@SuppressWarnings("deprecation") 
class BulbScheduler { 

public static void main(String args[]) throws InterruptedException{ 

    System.out.println("This is the main program"); 

    Timer timeOn = new Timer(); 
    Timer timeOff = new Timer(); 
    Bulb b1 = new Bulb("B1"); 
    BulbJob bjOn = new BulbJob(b1); 
    BulbJob bjOff = new BulbJob(b1); 

    bjOn.setBulbStateEqualTo(true);//Task - Turn bulb on 
    bjOff.setBulbStateEqualTo(false);//Task - Then turn the bulb off later 

    Date current = new Date();//Get current time and execute job ten seconds after this time 
    Date afterCurrent = (Date) current.clone(); 

    System.out.println("Current time is - " + current); 

    int currentSecs = current.getSeconds(); 
    int offset = 3;//number of seconds 

    afterCurrent.setSeconds(currentSecs + offset); 
    System.out.println("Future time is - " + afterCurrent); 

    timeOn.schedule(bjOn, afterCurrent);//Schedule job "bj" at time = afterCurrent 

    //Now turn the bulb off at new time = latest afterCurrent 
    afterCurrent.setSeconds(currentSecs + 2 * offset); 
    System.out.println("Future time is - " + afterCurrent); 

    timeOff.schedule(bjOff, afterCurrent); 

    System.out.println("Main program ends"); 

} 

} 
+0

주 스레드에서'주 프로그램 종료 '를 인쇄하고 있습니다 - 즉시 실행됩니다 ... 지연되기를 원하면 그것을 사용하여 작업을하고 전구를 끈 후에 실행하십시오. – assylias

+0

@assylias - 알겠습니다. EnProgram 작업을 만들 수 있습니다. 그러나, 나는 bjOff 후에 만 ​​그것을 실행해야 할 것이다. 이를 위해서는 매우 불편한 모든 타이밍을 추적해야합니다. 불행하게도, TimerTask에 대한 join() 메소드가 없다. 즉, task2가 완료된 후에 만 ​​task1을 완료한다. – Time

+1

차단 메커니즘 (예 : CountdownLatch)을 사용할 수도 있습니다. – assylias

0

. GreogarianCalendar를 사용해야합니다.

java.util.Date가 사용되지만 setSeconds를 사용할 수 없습니다. Javadoc을 읽기 매우 좋으며 많은 도움이됩니다. public void setSeconds (int seconds)

더 이상 사용되지 않습니다. JDK 버젼 1.1 이후는, Calendar.set (Calendar.SECOND, int seconds)로 옮겨졌습니다. 이 날짜의 초를 지정된 값으로 설정합니다. 이 Date 객체는 현지 시간대로 해석 된 것과 같이 년, 월, 일,시, 분을 이전과 동일하게 지정된 분 초의 특정 시점을 나타내도록 수정됩니다.

당신은

다음 날짜 객체를 얻고 타이머로 전송 GETDATE()를 사용 java.util.GregorianCalendar의 번호를 추가 (Calendar.SECOND, howManySeconds)를 사용합니다.

날짜에 setSecond를 호출해도 다른 필드는 변경되지 않습니다. Calendar.add의 Java 문서를 참조하십시오. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html 및 inro 클래스의 규칙을 참조하십시오.

0

타이머 개체의 일정 (TimerTask 작업, 긴 지연)도 사용할 수 있습니다. 지정한 지연 (밀리 초) 후에 지정된 작업을 실행하도록 예약합니다. 수정 된 코드 -

import java.util.*; 

class BulbScheduler { 

    private static java.text.SimpleDateFormat sdf1 = new java.text.SimpleDateFormat ("yy MM dd HH mm ss"); 

//helper  
static String formatDate(Date d){ 
     return sdf1.format(d); 
    } 

    public static void main(String args[]) throws InterruptedException{ 
     System.out.println("This is the main method"); 
     java.util.GregorianCalendar cal = new java.util.GregorianCalendar(); 

     Bulb b1 = new Bulb("bulb 1", false); 
     Bulb b2 = new Bulb("bulb 2", false); 

     System.out.println("Time now " + formatDate(cal.getTime())); 

     Timer timer = new Timer("bulbs"); 
     BulbJob b1On = new BulbJob(b1, true); 
     BulbJob b1Off = new BulbJob(b1, false); 
     BulbJob b2On = new BulbJob(b2, true); 
     BulbJob b2Off = new BulbJob(b2, false); 
     timer.schedule(b1On, 3 * 1000);//after 3 seconds 
     timer.schedule(b2On, 7 * 1000);//after 4 seconds 
     timer.schedule(b1Off, 6 * 1000);//after 6 seconds; before b2 on 

     b1On = new BulbJob(b1, true); 
     timer.schedule(b1On, 9 * 1000); 


     //if you want main to wait need to add code here to make it wait, 
     // but even if does the JVM wont exit. Its just a method. The JVM exits when all non daemon threads are done 
     // or System.exit is called 

     System.out.println("This is the main method ending; but other threads might be running ..."); 
     //main thread JVM waits for all other non dameons to end 

    } 

} 

변경된 BulbJob

수입하고있는 java.util. *;

클래스는 BulbJob의 TimerTask {

private Bulb bulbToHandle; 
private boolean bulbNewState;//dont start propert names with set 

//why a seperate property when we need to set the new state everytime and cannot reuse jobs? 
BulbJob(Bulb toHandle, boolean newState){ 
    this.bulbToHandle = toHandle; 
    bulbNewState= newState; 
} 

public void run(){ 
    this.bulbToHandle.setState(bulbNewState);//Set on or off 
} 

}

급 전구 ... 공개 setState를 공극 (부울 상태) { this.state = 상태를 연장;System.out.println ("Bulb"+ name + "은": "off") + "at"+ BulbScheduler.formatDate (new java.util.Date())) // 괜찮 으면

}