一、程序運行界面:
1、總控制台
2、計劃任務的設置界面。
3、控制台輸出結果。
二、程序開發環境:
使用Java(JDK 1.4)開發,圖形界面使用Eclipse (2.1.3版)的SWT方式開發。運行主機:P4 2.6+1G內存 windowsXP操作系統
三、預備。
開發此類程序,最好不要直接使用JAVA的線程來編程,這樣會增加不必要的復雜度和難度,吃力不討好。在JAVA中有一個包 java.util.Timer 這個包封裝了對線程的操作,我們可以把它稱做定時器類。我們先來看一個簡單例子:
import java.util.Timer;
import java.util.TimerTask;
public class Reminder {
Timer timer;
public Reminder(int seconds) {
timer = new Timer();
timer.schele(new RemindTask(),seconds*1000); //參數要求轉化成毫秒
}
public static void main(String args[]) {
new Reminder(5); //5秒後運行
}
/**一個內部類,封裝了所要運行的任務*/
class RemindTask extends TimerTask {
public void run() {
System.out.println("任務運行。。。。");
timer.cancel(); //結束timer中的所有任務
}
}
}
這里涉及於兩個JAVA類Timer和TimerTask。我們繼承TimerTask類後,將所要運行的任務封裝其run方法中;Timer可以管理幾千個任務(TimerTask),注意,同一個任務對象不能兩次加入到Timer中執行。
對(雖然執行的任務都一樣,但是兩個任務對象):
timer.schele(new RemindTask(), seconds * 1000);
timer.schele(new RemindTask(), seconds * 1000);
錯
RemindTask task= new RemindTask();
timer.schele(task, seconds * 1000);
timer.schele(task, seconds * 2000);
四、設計方案。
主要的類圖
說明:
任務類的設計。我們先創建一個抽象類AbstractTimerTask,這個類直接繼承至TimerTask類,提供對TimerTask封裝。然後所有具體的任務類(如:TimerTask_1)繼承自AbstractTimerTask。
import java.util.TimerTask;
public abstract class AbstractTimerTask extends TimerTask {
TaskEntry taskEntry; //任務記錄
public AbstractTimerTask(TaskEntry taskEntry) {
this.taskEntry = taskEntry;
}
/*
* 生成一個新的實例相當於克隆自身;原因在於:同一任務對象不能兩次加入到Timer
* 在TaskEntry類將看到它的使用方法
*/
abstract AbstractTimerTask getCloneObject();
}
下面是它的一個實現類的源代碼我們可以將要運行任務的代碼寫在這個類中。
import java.util.Calendar;
public class TimerTask_1 extends AbstractTimerTask {
public TimerTask_1(TaskEntry taskEntry) { //構造方法
super(taskEntry);
}
public AbstractTimerTask getCloneObject() {
return new TimerTask_1(taskEntry);
}
public void run() {
/*在這里寫你要執行的程序。。。。。*/
System.out.println("??時:"+taskEntry.getName()+"運行了一次");
this.taskEntry.taskStart(); //運行下一個時間點任務
}
}
在AbstractTimerTask類有一個TaskEntry欄位,這是本設計的一個核心類,它代表一條封裝完整的任務記錄,每個任務類和它的運行計劃都封裝在這條類中,源代碼如下。Timer和AbstractTimerTask前面都已說過,那麼TimePlan是做什麼用的呢?
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import mytimer.util.Util;
/**任務記錄類*/
public class TaskEntry {
public static final int TASK_START = 0; //定義兩個表示任務記錄狀態常量
public static final int TASK_STOP = 1;
private Long oid; //任務ID號,唯一
private String name; //任務名稱
private int state = TASK_STOP; //任務狀態(啟動/停止)
private Timer timer; //JAVA計時器
private TimePlan timePlan; //時間計劃的類型
private AbstractTimerTask timerTask; //任務類的種子對象,由這個對象來不斷克隆
private AbstractTimerTask runTimerTask; //運行計劃的當前任務
/**
* ITaskEntry.taskStart()-->TimerTask.run()-->ITaskEntry.taskStart()
* 形成一個循環迴路。本方法負責起動本類代表的任務
*/
public void taskStart() {
if (timePlan.haveNext()) {
Date date = timePlan.nextDate();//得到任務計劃時間
runTimerTask = timerTask.getCloneObject();//得到任務(復制)
timer.schele(runTimerTask, date); //加入計劃隊列
//列印將要運行的計劃任務的信息
Calendar c = Calendar.getInstance();
c.setTimeInMillis(runTimerTask.scheledExecutionTime());
System.out.println(Util.dateToLongStr(c.getTime())+"將運行"+name);
} else {
state = TASK_STOP;
System.out.println(name + "結束");
}
}
/**停止任務*/
public void taskStop() {
if (runTimerTask != null) {
//列印信息
Calendar c = Calendar.getInstance();
c.setTimeInMillis(runTimerTask.scheledExecutionTime());
System.out.println("計劃於:"+Util.dateToLongStr(c.getTime())+"運行的" + name + "被終止");
//終止本任務, 調用Timer.cancel()是終止Timer的所有任務。
runTimerTask.cancel();
} else {
System.out.println(name + "未進入執行計劃");
}
}
……… 一些屬性的get/set方法(省略)
/** 監聽類(內部類) */
public static class DateBeforeTodayException extends NullPointerException {
private Date date;
public DateBeforeTodayException(Date date) {this.date = date;}
public String toString() {
return "計劃時間(" + Util.dateToLongStr(date) + ")早於當前時間";
}
}
}
1、TimePlan是一個介面(interface),它是表示「運行計劃的方案」,這個程序中提供了三種運行計劃方案(見前圖:計劃任務的設置界面):
一次性運行。
每隔一個時間段運行。
一周中選擇那幾天運行。
將它設計成一個介面是為了方便今後擴展,如果要新增新的時間方案只需要繼承這個介面寫一個新的實現即可。三種時間方案的類圖如下:
說明:
a) TimePlan封裝了五個方法,其它haveNext()和nextDate()最重要,這個兩個方法模仿了Java中集合類(Collection)的迭代器(Iterator)的設計形式,代碼如下:
import java.util.Date;
//時間計劃方案的介面
public interface TimePlan {
boolean haveNext();//判斷還有沒有下一個計劃時間
Date nextDate();//得到下一個計劃時間
Date getCurrentDate();//得到開始時間
void setCurrentDate(Date date); //設計開始時間
String getTimePlanString();//顯示運行計劃方案的文字說明
}
b) AbstractTimePlan是這個抽象類,主要目的是將一些各子類的公共方法寫在這里。代碼如下:
import java.util.Date;
public abstract class AbstractTimePlan implements TimePlan {
//記錄計劃的第一時間點,除設置新的起始時間,否則不再改變
protected Date currentDate;
/*
當前計劃的時間點,每次計劃替換時被更新,
似乎這個才應叫cureentDate,sorry不想再改了
*/
protected Date planDate;
public boolean haveNext() {
return (planDate != null);
}
public Date getCurrentDate() {
return currentDate;
}
public void setCurrentDate(Date date) {
currentDate = date;
planDate = date; //在賦給currentDate值時,同時也賦給planDate
}
}
c) 然後我們看看三種計劃方案的實現類的源代碼:
//「一次性運行」的計劃方案類
import java.util.Date;
public class TimePlanOnce extends AbstractTimePlan {
public Date nextDate() {
//把要當前的計劃時間保存在中間變數中
Date returnDate = this.planDate;
//算出下一個計劃時間。沒有下一個就設為null
this.planDate = null;
//判斷一下計劃時間合不合條件
if (returnDate == null)
throw new NullPointerException("沒有下一個計劃日期");
return returnDate;
}
public String getTimePlanString() {
return "一次性運行,運行時間: (列印this.currentDate) ";
}
}
//「周期性間隔」的時間計劃方案類
import java.util.Date;
public class TimePlanPeriod extends AbstractTimePlan {
public static final int HOUR = 0;
public static final int DAY = 1;
private int spaceTime; //間隔時間,單位毫秒
private int timeType;
public Date nextDate() {
//把要當前的計劃時間保存在中間變數中
Date returnDate = this.planDate;
//算出下一個計劃時間。沒有下一個就設為null
int milliSecond = 0;
if (timeType ==HOUR) milliSecond = spaceTime * 1000; //小時*60*60*1000;
if (timeType ==DAY) milliSecond = spaceTime * 24 * 60 * 60 * 1000; //天
planDate = Util.DateAddSpaceMilliSecond(planDate, milliSecond);
//判斷一下計劃時間合不合條件
if (returnDate == null)
throw new NullPointerException("沒有下一個計劃日期");
return returnDate;
}
public String getTimePlanString() {
if (timeType == HOUR)
return "第一次運行於:currentDate.並每隔spaceTime小時運行一次";
if (timeType == DAY)
return "第一次運行於:currentDate.並每隔spaceTime天運行一次";
return "";
}
public int getSpaceTime() { return spaceTime; }
public int getTimeType() { return timeType; }
public void setSpaceTime(int i) { spaceTime = i; }
public void setTimeType(int i) { timeType = i; }
}
/**選擇一周的某幾天,讓這幾天在同一時間點運行任務, 一周內必須選擇一天*/
import java.util.Calendar;
import java.util.Date;
public class TimePlanSelectWeek extends AbstractTimePlan {
private static Calendar c = Calendar.getInstance(); //取得一個日歷實例
private static int spaceMilliSecond = 0; //間隔時間,單位毫秒
private boolean[] selectWeek = new boolean[7]; //0為星期日 ,1為星期一
public Date nextDate() {
Date returnDate = null;
if (!isSelectWeek(planDate)) //如果這一天不是所選周中的一天
planDate = getNextDate(planDate);
returnDate = planDate;
planDate = getNextDate(planDate);
//判斷一下計劃時間合不合條件
if (returnDate == null)
throw new NullPointerException("沒有下一個計劃日期");
return returnDate;
}
//算出下一個計劃時間。沒有下一個就設為null
private Date getNextDate(Date date) {
Date tempDate = date;
Date returnDate = null;
for (int i = 0; i < 7; i++) {
tempDate = Util.DateAddSpaceMilliSecond(tempDate, spaceMilliSecond);
if (isSelectWeek(tempDate)) {
returnDate = tempDate;
break;
}
}
return returnDate;
}
/**設置某星期是否被選, 0為星期日 ,1為星期一....6為星期六*/
public void setSelectWeek(int i, boolean b) {selectWeek[i] = b;}
/** 判斷某星期是否被選*/
public boolean isSelectWeek(int i) {return selectWeek[i];}
/**判斷某天所屬星期幾是否被選*/
public boolean isSelectWeek(Date date) {
if (date == null) return false;
c.setTime(date);
//Calendar.DAY_OF_WEEK:星期日=1,星期六=7 c.get(Calendar.DAY_OF_WEEK)
return isSelectWeek(c.get(Calendar.DAY_OF_WEEK) - 1);
}
public String getTimePlanString() {
StringBuffer sb = new StringBuffer("");
if (selectWeek[1]) sb.append("周一,");
if (selectWeek[2]) sb.append("周二,");
if (selectWeek[3]) sb.append("周三,");
if (selectWeek[4]) sb.append("周四,");
if (selectWeek[5]) sb.append("周五,");
if (selectWeek[6]) sb.append("周六,");
if (selectWeek[0]) sb.append("周日,");
return "每周的"+sb.toString()+"運行";
}
}
TimerTask的工廠類。將生成TimerTask的代碼另起一個類的好處是代碼的層次比較清楚,也比較好管理。由於TimerTask包含有幾個欄位,因此產生一個TimerTask對象還是有一定的復雜度,建立一個專門生成TimerTask的工廠類,這樣我們在生成一個TimerTask對象時就可以少掉很多麻煩的代碼了。當然由於我的工作任務,只需要一個TimerTask對象就夠了,所以最初之前我是將它直接寫在圖形界面的代碼里的。
這里建立一個TimerTask對象池tasks,它是一個靜態變數,這樣在getInstance時不必總是要新生成一個TimerTask。還有Timer也是一個靜態變數,它是一個全局單例(是最簡單的單例模式了),因為前面說了Timer可以管理幾千個任務,所以Timer對象一個就夠了。
import java.util.HashMap;
import java.util.Timer;
public class TaskEntryFactory {
private static final HashMap tasks = new HashMap();
private static final Timer timer = new Timer();
public static TaskEntry getInstance(Long oid, String name) {
if (tasks.containsKey(oid)) {
return (TaskEntry) tasks.get(oid);
} else {
TaskEntry entry = new TaskEntry();
entry.setOid(oid);
entry.setName(name);
entry.setTimer(timer);
entry.setTimerTask(new TimerTask_1(entry));
tasks.put(oid, entry);
return entry;
}
}
}
起動和停止任務,當「任務設置界面(TaskListDialog.java)」點擊OK後處理。界面的編寫就不在本文討論的范圍內了。
//任務設置界面中點擊」確認(OK)」按鈕後的處理
if (dialog.open() == Window.OK) {
if (taskEntry.getState() == TaskEntry.TASK_START) {
taskEntry.taskStop();//將舊的停掉
taskEntry.taskStart();//開始新設置的
}
if (taskEntry.getState() == TaskEntry.TASK_STOP)
taskEntry.taskStop();
tv.refresh(taskEntry);
}
㈡ 用java寫一個後台服務,怎麼做啊,沒有學過,根本不知道,求詳細解答
最簡單的,後台用servlet寫,然後客戶端通過Http協議向伺服器端版發送請求,伺服器端通過tomcat容器接受HttpRequest請求,然後權向客戶端反饋HttpResponse響應。我看您還是把servlet學完在搞吧
㈢ 怎樣學習JAVA,JAVA基礎教程之入門學習方法
入門要一步一步完成,需要在途中為自己確立一個一個的目標來完成。下面為大家介紹一下,依照這樣的目標完成,相信你一定會成為高手!
如何學習java,從易到難再到易的過程,一步一個腳印去學習,嚴格意義上說,java是一門較復雜的編程語言,沒有幾年時間的苦功,不可能學到非常好的層次。同樣,學習java為了最快的提升效率和保證你能夠學會。還是需要報個培訓班,或者聽一下網上的網路教程。
㈣ JAVA基礎入門教程 -
我是學java的,給你推薦幾本,《Java核心編程》,《Java編程思想》《Java高手真經》,至於學習視頻呢,我認為可以到siki學院看下。老師講的都很用心。