Author: Chen Gang, Guilin, 97, graduated from the Department of Mathematics, Guangxi Normal University, temporarily at IBM China Research Center, a part-time engaged in software development, focus on java platform software development (2004.2-?). Email: Glchengang@hotmail.com Blog: Glchengang.yeah.net Many systems require a program that runs uninterrupted in the background to periodically perform certain system tasks. This is similar to the functionality of the program tasks from Windows. I participated in the development of a network management project of a provincial Unicom for a year and a half before, and I have written such a background program. It should be uninterrupted from various types of data files (each file has Agreement) and interpret these files into a record into the database. This background program uses the thread in Java. Due to the complexity of the thread, it is difficult to debug, very unfortunate this background program is very unstable, and there will be one or two times a week will stop in the process, the reason is not found today. Behind my heart.
Taining today, I have been fortunate to participate in IBM a development project. This project also needs a similar background running program. The task of this program is to check the data in the database every other day, and perform actions in accordance with certain conditional records. The task is very simple. For the future expansion, I designed this into a multi-task-managed background program. Week did not set up two tasks in the same time, once every 10 seconds, another task executed every 1 second, running two days, running is good. It is estimated that many friends will face the same problem with me, here will publish the procedures and code, and hope to have interest to study.
First, the program run interface:
1, the total console
2, the setting interface of the planned task.
3, the console output result.
Second, the program development environment:
Developed with Java (JDK 1.4), the graphical interface develops using the Eclipse (version 2.1.3) SWT mode. Run host: P4 2.6 1G memory WindowsXP operating system
Third, prepare.
Develop such programs, it is best not to use Java threads to program, which will increase unnecessary complexity and difficulty, and effort is not good. There is a package java.util.timer in Java package to encapsulate a thread, we can call it to schedule. Let's first look at a simple example:
Import java.util.timer;
Import java.util.timertask;
public
Class Reminder {
Timer Timer;
Public Reminder
INT Seconds) {
Timer =
New Timer ();
Timer.schedule
New transindtask (), seconds * 1000); // parameter requirements are converted into milliseconds
}
public
Static
void main (string args []) {
New Reminder (5); // 5 seconds after running
}
/ ** An internal class that encapsulates the task to run * /
Class Remindtask
Extends Timertask {
public
Void Run () {
System.out.println ("Task Run ...");
Timer.cancel (); // End all the tasks in Timer
}
}
}
Here, there are two Java class Timer and Timertask. After we inherit the Timertask class, we will encapsulate its RUN method; Timer can manage thousands of tasks (Timertask), note that the same task object cannot be added twice to the Timer. For pairs (although the task of execution is the same, two task objects):
Timer.schedule
New remindtask (), seconds * 1000);
Timer.schedule
New remindtask (), seconds * 1000);
wrong
Remindtask Task =
New remindtask ();
Timer.schedule (Task, Seconds * 1000);
Timer.schedule (Task, Seconds * 2000);
Fourth, design.
Main class diagram
Description:
Design of the mission class. Let's create an abstract class AbstractTimertask, this class directly into the Timertask class, providing Timertask package. Then all specific tasks (such as: Timertask_1) inherit from AbstractTimertask.
Import java.util.timertask;
public
Abstract
Class AbstractTimertask
Extends Timertask {
Taskentry taskentry; // Task Record
Public AbstractTimertask (Taskentry Taskentry) {
THIS.TASKENTRY = Taskentry;
}
/ *
* Generate a new instance is equivalent to cloning itself; the reason is:
The same task object cannot be added twice to Timer
* The Taskentry class will see its method
* /
Abstract AbstractTimertask getCloneObject ();
}
Below is a source code for its implementation. We can write the code to run the task in this class.
Import java.util.calendar;
public
Class Timertask_1
Extends abstracttimertask {
PUBLIC TIMERTASK_1 (Taskentry Taskentry) {// Construction Method
Super (taskentry);
}
Public AbstractTimertask getCloneObject () {
Return
NEW TIMERTASK_1 (Taskentry);
}
public
Void Run () {
/ * Write the program you want to perform here. . . . . * /
System.out.println ("??:" taskentry.getname () "Run once");
this.taskentry.taskstart (); // Run the next time point task
}
}
In the AbstractTimertask class, there is a taskenTry field, which is a core class of this design. It represents a complete task record, each task class, and its running plan are packaged in this class, the source code is as follows. Timer and AbstractTimertask have said before, then what is TimePlan to do?
Import java.util.calendar;
Import java.util.date;
Import java.util.timer;
Import mytimer.util.util;
/ ** Task record class * /
public
Class taskentry {
public
Static
Final
INT task_start = 0; // Defines two representation task recording state constants public
Static
Final
INT task_stop = 1;
Private long Oid; // Task ID number, unique
Private string name; // Task Name
Private
Int state = task_stop; // task status (start / stop)
Private Timer Timer; // Java Timer
PRIVATE TIMEPLAN TIMEPLAN; // Time Plan Type
Private AbstractTimertask Timertask; // The seed object of the task class, is constantly cloned by this object
Private AbstractTimertask runtimertask; // Current task of running plan
/ **
* Itaskentry.taskstart () -> Timertask.run () -> itaskentry.taskstart ()
* Form a loop loop. This method is responsible for starting the tasks of this class
* /
public
Void taskstart () {
IF (TimePlan.Havenext ()) {
Date Date = Timeplan.nextdate (); // Get task planning time
Runtimertask = Timertask.getCloneObject (); // Get a task (copy)
Timer.schedule (runtimertask, date); // joining the plan queue
// Print information about the planned task to run
Calendar c = calendar.getInstance ();
C.SetTimeInmillis (RuntimeTask.scheduledExecutionTime ());
System.out.println (Util.Datetolongstr (c.gettime ()) "will run" name);
}
Else {
State = Task_Stop;
System.out.println (Name "End");
}
}
/ ** Stop Task * /
public
Void taskstop () {
IF (runtimertask! =
NULL) {
// Print information
Calendar c = calendar.getInstance ();
C.SetTimeInmillis (RuntimeTask.scheduledExecutionTime ());
System.out.println ("Plan:" Util.datetolongstr (C.getTime ()) "Run" Name "Termination");
// Terminate this task, call timer.cancel () is to terminate all tasks in Timer.
Runtimertask.cancel ();
}
Else {
System.out.println (Name "Not Entering Executive Plan");
}
}
......... Get / set method for some properties (omitted)
/ ** Listening class (internal class) * /
public
Static
Class DatebeforeTodayException
Extends nullpointerserException {
PRIVATE DATE;
Public DatebeforeToDayException (Date Date) {
THIS.DATE = DATE;
Public string toString () {
Return "plan time (" Util.Datetolongstr (Date)) is earlier than the current time ";
}
}
1. Timeplan is an interface (INTERFACE), which means "Run Plan", which provides three run planning schemes (see the front image: Planning task setting interface):
One-time operation.
Run every other period of time.
Choose that day of running in a week.
It is designed to be an interface to expand in the future. If you want to add new time schemes, you only need to inherit this interface to write a new implementation. The class diagrams of three time schemes are as follows:
Description:
a) TimePlan encapsulates five methods, other Havenext () and Nextdate () most important, this two methods imitate the design form of the collection of collections in Java, the code is as follows:
Import java.util.date;
// Time Planning Program
public
Interface Timeplan {
Boolean Havenext (); // Judging that there is no next planning time
Date nextddate (); // Get the next planning time
Date getcurrentdate (); // get start time
Void setCurrentDate (Date Date); // Design start time
String getTimeplanString (); // Show text description of the running plan solution
}
b) AbstractTimePlan is this abstract class, main purpose is to write a public method of some subclasses here. code show as below:
Import java.util.date;
public
Abstract
Class AbstractTimePlan
Implements TimePlan {
// Record the first point of time of the plan, except for the new start time, otherwise no longer change
Protected Date Currentdate;
/ *
When the time point of the current plan, it is updated every time you plan.
It seems that this should be called CurentDate, Sorry doesn't want to change again.
* /
Protected Date Plandate;
public
Boolean HAVENEXT () {
Return (Plandate! =
NULL);
}
Public Date getcurrentdate () {
Return Currentdate;
}
public
Void setcurrentdate (date date) {
Currentdate = DATE;
PLANDATE = DATE; // When assigns a currentdate value, it also assigns a Plandate.
}
}
c) Then we look at the source code of the three planning schemes:
// "One-time operation" plan plan
Import java.util.date;
public
Class TimePlanonce
Extends AbstractTimePlan {
Public Date nextDate () {
/ / Save the current planning time in the intermediate variable
Date returndate =
this.plandate;
// Call the next planning time. No next one is set to NULL
this.plandate =
NULL;
/ / Judgment the planning time without condition
IF (returndate ==
NULL)
Throw
New NullPointersRexception ("No Next Plan Date");
Return Returndate;
}
Public string gettimeplanstring () {return "runs at once, running time: (Print this.currentdate)";
}
}
// "Periodic Interval" Time Plan Program
Import java.util.date;
public
Class TimePlanperiod
Extends AbstractTimePlan {
public
Static
Final
INT Hour = 0;
public
Static
Final
INT day = 1;
Private
INT SPATITIME; // Interval, unit millisecond
Private
int TimeType;
Public Date nextDate () {
/ / Save the current planning time in the intermediate variable
Date returndate =
this.plandate;
// Call the next planning time. No next one is set to NULL
INT MilliseCond = 0;
IF (TimeType == Hour) MilliseCond = SpaceTime * 1000; // hour * 60 * 60 * 1000;
IF (TimeType == Day) MilliseCond = SpaceTime * 24 * 60 * 60 * 1000; //
Plandate = Util.dateAddspaceMilliseCond (Plandate, MilliseCond);
/ / Judgment the planning time without condition
IF (returndate ==
NULL)
Throw
New NullPointersRexception ("No Next Plan Date");
Return Returndate;
}
Public string gettimeplanstring () {
IF (TimeType == Hour)
RETURN "The first time runs on: Currentdate. and run once every spacetime hour";
IF (TimeType == Day)
Return "is running on: Currentdate. Every time Spacetime is running once."
""; "
}
public
INT getSpacetime () {
Return SpaceTime;}
public
INT getTimetyPE () {
Return TimeType;}
public
Void setspaceetime
INT i) {spacetime = i;}
public
Void setTimetyPE
INT i) {TIMETYPE = i;}
}
/ ** Select a few days for a week, let this day to run the task at the same time, you must choose one day in the week * /
Import java.util.calendar;
Import java.util.date;
public
Class TimeplanselectWeek
Extends AbstractTimePlan {
Private
Static Calendar C = Calendar.GetInstance (); // Get a calendar instance
Private
Static
INT SpaceMilliseCond = 0; // Interval, unit milliseconds
Private
Boolean [] SelectWeek =
New
Boolean [7]; // 0 is Sunday, 1 is Monday
Public Date nextDate () {
Date returndate =
NULL;
if (! isselectweek (plandate)) // If this day is not a day, the day, a day, a day, PLANDATE = GetNextDate (Plandate);
Returndate = plandate;
PLANDATE = GetNextdate (Plandate);
/ / Judgment the planning time without condition
IF (returndate ==
NULL)
Throw
New NullPointersRexception ("No Next Plan Date");
Return Returndate;
}
// Call the next planning time. No next one is set to 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;
}
/ ** Set whether it is selected for a week, 0 is Sunday, 1 is Monday .... 6 is Saturday * /
public
Void setSelectWeek
INT i,
Boolean b) {selectweek [i] = b;}
/ ** Judging whether a week is selected * /
public
Boolean IsselectWeek
INT i) {
Return SelectWeek [I];
/ ** Judge whether the day of the day is selected * /
public
Boolean isselectWeek (Date Date) {
IF (Date ==
NULL)
Return
False;
C.SetTime (date);
//Calendar.day_of_week: Sunday = 1, Saturday = 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 ("Monday,");
IF (SelectWeek [2]) sb.append ("Tuesday,");
IF (SelectWeek [3]) sb.append ("Wednesday,");
IF (SelectWeek [4]) sb.append ("Thursday,");
IF (SelectWeek [5]) sb.append ("Friday,");
IF (SelectWeek [6]) sb.append ("Six,");
IF (SelectWeek [0]) SB.Append ("Sunday,");
Return "Weekly" Sb.toString () "Run";
}
}
Timertask's factory class. The advantage of another class of code that generates Timertask is that the level of the code is clear, and it is better to manage. Since Timertask contains several fields, a Timertask object is generated or has a certain complexity, build a factory class specifically generated Timertask so that we can lose a lot of trouble when generating a Timertask object. Of course, because of my job task, I only need a Timertask object enough, so I first wrote it directly in the code interface. Here is a Timertask object pool Tasks, which is a static variable so that you don't have to create a Timertask when getInstance. There is also a static variable, which is a global single example (which is the simplest single case mode), because the Timer can manage thousands of tasks, so the Timer object is enough.
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;
}
}
}
Start and stop tasks, when the task setting interface (TaskListDialog.java "clicks OK processing. The writing of the interface is not within the scope of this article.
// Table of the Task Setting Interface Click "Confirm (OK)" button after the button
IF (Dialog.Open () == WINDOW.OK) {
IF (Taskentry.getState () == taskentry.task_start) {
Taskentry.taskstop (); // Stop the old stop
Taskentry.taskStart (); // Start new settings
}
IF (taskeTry.getState () == taskentry.task_stop)
Taskentry.taskstop ();
TV.Refresh (taskentry);
}