Java tutorial
/* * * Copyright (c) 1997-1999 Scott Oaks and Henry Wong. All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and * without fee is hereby granted. * * This sample source code is provided for example only, * on an unsupported, as-is basis. * * AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. AUTHOR SHALL NOT BE LIABLE FOR * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. * * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). AUTHOR * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR * HIGH RISK ACTIVITIES. */ import java.util.*; public class JobScheduler implements Runnable { final public static int ONCE = 1; final public static int FOREVER = -1; final public static long HOURLY = (long) 60 * 60 * 1000; final public static long DAILY = 24 * HOURLY; final public static long WEEKLY = 7 * DAILY; final public static long MONTHLY = -1; final public static long YEARLY = -2; private class JobNode { public Runnable job; public Date executeAt; public long interval; public int count; } private ThreadPool tp; private DaemonLock dlock = new DaemonLock(); private Vector jobs = new Vector(100); public JobScheduler(int poolSize) { tp = (poolSize > 0) ? new ThreadPool(poolSize) : null; Thread js = new Thread(this); js.setDaemon(true); js.start(); } private synchronized void addJob(JobNode job) { dlock.acquire(); jobs.addElement(job); notify(); } private synchronized void deleteJob(Runnable job) { for (int i = 0; i < jobs.size(); i++) { if (((JobNode) jobs.elementAt(i)).job == job) { jobs.removeElementAt(i); dlock.release(); break; } } } private JobNode updateJobNode(JobNode jn) { Calendar cal = Calendar.getInstance(); cal.setTime(jn.executeAt); if (jn.interval == MONTHLY) { // There is a minor bug. (see java.util.calendar) cal.add(Calendar.MONTH, 1); jn.executeAt = cal.getTime(); } else if (jn.interval == YEARLY) { cal.add(Calendar.YEAR, 1); jn.executeAt = cal.getTime(); } else { jn.executeAt = new Date(jn.executeAt.getTime() + jn.interval); } jn.count = (jn.count == FOREVER) ? FOREVER : jn.count - 1; return (jn.count != 0) ? jn : null; } private synchronized long runJobs() { long minDiff = Long.MAX_VALUE; long now = System.currentTimeMillis(); for (int i = 0; i < jobs.size();) { JobNode jn = (JobNode) jobs.elementAt(i); if (jn.executeAt.getTime() <= now) { if (tp != null) { tp.addRequest(jn.job); } else { Thread jt = new Thread(jn.job); jt.setDaemon(false); jt.start(); } if (updateJobNode(jn) == null) { jobs.removeElementAt(i); dlock.release(); } } else { long diff = jn.executeAt.getTime() - now; minDiff = Math.min(diff, minDiff); i++; } } return minDiff; } public synchronized void run() { while (true) { long waitTime = runJobs(); try { wait(waitTime); } catch (Exception e) { } ; } } public void execute(Runnable job) { executeIn(job, (long) 0); } public void executeIn(Runnable job, long millis) { executeInAndRepeat(job, millis, 1000, ONCE); } public void executeInAndRepeat(Runnable job, long millis, long repeat) { executeInAndRepeat(job, millis, repeat, FOREVER); } public void executeInAndRepeat(Runnable job, long millis, long repeat, int count) { Date when = new Date(System.currentTimeMillis() + millis); executeAtAndRepeat(job, when, repeat, count); } public void executeAt(Runnable job, Date when) { executeAtAndRepeat(job, when, 1000, ONCE); } public void executeAtAndRepeat(Runnable job, Date when, long repeat) { executeAtAndRepeat(job, when, repeat, FOREVER); } public void executeAtAndRepeat(Runnable job, Date when, long repeat, int count) { JobNode jn = new JobNode(); jn.job = job; jn.executeAt = when; jn.interval = repeat; jn.count = count; addJob(jn); } public void cancel(Runnable job) { deleteJob(job); } public void executeAtNextDOW(Runnable job, Date when, int DOW) { Calendar target = Calendar.getInstance(); target.setTime(when); while (target.get(Calendar.DAY_OF_WEEK) != DOW) target.add(Calendar.DATE, 1); executeAt(job, target.getTime()); } public void configureBackup(Runnable job) { Calendar now = Calendar.getInstance(); executeAtNextDOW(job, now.getTime(), Calendar.SUNDAY); } public static void main(String[] args) throws Exception { Runnable r1 = new Runnable() { public void run() { System.out.print("1"); try { Thread.sleep(5000); } catch (Exception ex) { } ; System.out.print("1"); } }; Runnable r2 = new Runnable() { public void run() { System.out.print("2"); try { Thread.sleep(5000); } catch (Exception ex) { } ; System.out.print("2"); } }; Runnable r3 = new Runnable() { public void run() { System.out.print("3"); } }; Runnable r4 = new Runnable() { public void run() { System.out.print("4"); } }; JobScheduler js = new JobScheduler(0); Thread.sleep(1000); // Test 1 - General Test js.executeInAndRepeat(r1, 10000, 3000, 10); js.executeInAndRepeat(r2, 20000, 1000, 10); //Thread.sleep(11000); //js.cancel(r1); //js.cancel(r2); //js.configureBackup(r1); // Test 2 - Signature Test //Date in10Sec = new Date(System.currentTimeMillis()+10000L); //js.execute(r1); //js.executeIn(r2, 2000L); //js.executeInAndRepeat(r3, 10000L, 2000L); //js.executeInAndRepeat(r4, 10000L, 2000L, 5); //js.executeAt(r1, in10Sec); //js.executeAtAndRepeat(r2, in10Sec, 2000L); //js.executeAtAndRepeat(r3, in10Sec, 1000L, 5); //js.cancel(r4); //Thread.sleep(20000L); //js.cancel(r2); // Test 3 - Interval Test //js.executeInAndRepeat(r3, 10000L, JobScheduler.HOURLY); //js.executeInAndRepeat(r3, 10000L, JobScheduler.DAILY); //js.executeInAndRepeat(r3, 10000L, JobScheduler.WEEKLY); //js.executeInAndRepeat(r3, 10000L, JobScheduler.MONTHLY); //js.executeInAndRepeat(r3, 10000L, JobScheduler.YEARLY); } }