2013-03-11 60 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; 

} 


} 

BulbJob類,這是一TimerTask

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類 - 此時間表時,燈泡被接通或關斷。

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用於在普通'Thread'的'sleep()'上選擇'TimerTask'。 – asgs 2013-03-11 08:25:37

+0

@asgs - 如何讓「主程序結束」只有在執行完所有內容後纔會出現? – Time 2013-03-11 08:34:39

+1

由於主線程並不依賴於您的工作,恐怕您需要重新設計,以便您可以使用Thread的join()方法等待TimerTask完成。 – asgs 2013-03-11 08:43:07

回答

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秒時關閉同一個燈泡我是否必須創建新的BulbJob或定時器才能關閉它? – Time 2013-03-11 08:52:52

+1

創建3個任務:turnBulbOn,turnBulbOff,ExitProgram,執行這些操作並在其他,你只需要一個定時器 – assylias 2013-03-11 08:52:52

+0

你有沒有用程序退出作爲一個單獨的'TimerTask'是你最好的選擇 – asgs 2013-03-11 08:54:13

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 2013-03-11 09:07:01

+0

@assylias - 好吧。我可以製作EnProgram任務。但是,我必須在bjOff之後才能運行它。爲此,我必須跟蹤所有非常不方便的時機。不幸的是,TimerTask沒有join()方法,即只有在task2完成後才完成task1。 – Time 2013-03-11 09:10:30

+1

您也可以使用阻止機制,例如CountdownLatch。 – assylias 2013-03-11 09:49:56

0

你沒有正確設置時間。需要使用GreogarianCalendar。

java.util.Date被使用,但不能使用它的setSeconds閱讀Javadoc其相當不錯,將有很大幫助。 public void setSeconds(int seconds)

已棄用。從JDK版本1.1開始,由Calendar.set(Calendar.SECOND,int seconds)取代。 將此日期的秒數設置爲指定值。此Date對象被修改,以便它代表在一分鐘的指定秒鐘內的時間點,其中年,月,日,小時和分鐘與以前相同,如本地時區中所解釋的。

您需要使用的java.util.GregorianCalendar#加(Calendar.SECOND,howManySeconds)

然後使用GETDATE()來獲取日期對象,並將其發送到定時器。

調用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 =狀態; (「Bulb」+ name +「is」+(state?「on」:「off」)+「at」+ BulbScheduler.formatDate(new java.util.Date())); //如果還可以

}