【代码积累】Simulate schedule service

import java.util.Collections;


public class Test {
	public void test() {
		SScheduleExecutor scheduledThreadpool = new SScheduleExecutor();
		System.out.println("Main test:time stamp = "+System.currentTimeMillis()/1000);  /*显示以秒为单位*/
		scheduledThreadpool.submit(new NormalWork(), 2000);   /*以毫秒为单位*/
		scheduledThreadpool.submit(new LoopWork(), 3000, 6000);
	}
	
	private class LoopWork implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			System.out.println("LoopWork,time stamp = "+System.currentTimeMillis()/1000);
		}
		
	}
	
	private class NormalWork implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			System.out.println("NormalWork,time stamp = "+System.currentTimeMillis()/1000);
		}
		
	}
}

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;




public abstract class DelayTask implements Delayed{
	protected Runnable command = null;
	protected long iniDelay = -1; /*in milliseconds*/
	
	public DelayTask() {
		
	}
	
	public Runnable getTask() {
		return command;
	}
	
	@Override
	/*返回:
	 * 负值:当前对象小于输入对象
	 * zero:当前对象等于输入对象
	 * 正值:当前对象大于输入对象*/
	public int compareTo(Delayed o) {
		// TODO Auto-generated method stub
		long defference = iniDelay - o.getDelay(TimeUnit.MILLISECONDS);		
		return (defference < 0) ? -1 : (defference > 0) ? 1 : 0;
	}
}



public class DelayTaskFactory {
	public DelayTask createDelayTask(Runnable command,long iniDelay) {
		return new NormalDelayTask(command,iniDelay);
	}
	
	public DelayTask createDelayTask(Runnable command,long iniDelay,long period) {
		return new LoopTask(command, iniDelay, period);
	}
}

import java.util.concurrent.TimeUnit;




public class LoopTask extends DelayTask{
	private long period = -1;
	private long periodTimeStamp = -1;
	private boolean isFirstRun = true;  /*第一次执行后置为false*/
	
	public LoopTask(Runnable command,long iniDelay,long period) {
		super();
		this.command = command;
		this.iniDelay = System.currentTimeMillis()+iniDelay;
		this.period = period;
	}
	
	@Override
	public long getDelay(TimeUnit unit) {
		// TODO Auto-generated method stub
		if( false == isFirstRun && -1 != period ) {
			/*周期任务,非第一次执行,返回period*/
			return periodTimeStamp-System.currentTimeMillis();
		}


		return iniDelay-System.currentTimeMillis();
	}
	
	private void setFirstRunFalse() { isFirstRun = false; };
	private void setFirstRunTrue() { isFirstRun = true; }
	
	public void resetTask() {
		setFirstRunFalse();
		periodTimeStamp = System.currentTimeMillis()+period;
	}
}

import java.util.concurrent.TimeUnit;




public class NormalDelayTask extends DelayTask{
	
	public NormalDelayTask(Runnable command,long iniDelay) {  /*暂时默认以毫秒为单位*/
		super();  
		this.command = command;
		this.iniDelay = System.currentTimeMillis()+iniDelay;
	}
	
	@Override
	public long getDelay(TimeUnit unit) {  /*暂时默认以毫秒为单位*/
		// TODO Auto-generated method stub
		return iniDelay-System.currentTimeMillis();
	}
}



public interface SExecutorService {
	public void submit(Runnable r,long delay,long period);
	public void submit(Runnable r,long delay);
}

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;




public class SScheduleExecutor implements SExecutorService{
	/*内部保存一个线程池,用来产生consumer,线程池暂定无界;producer则是每次调用submit,SScheduleExecutor自己;
	 * 内部保存一个DelayQueue*/
	private ExecutorService threadpool = Executors.newCachedThreadPool();
	private BlockingQueue<Delayed> delayQueue = new DelayQueue<Delayed>();	
	private DelayTaskFactory taskFac = new DelayTaskFactory();
	private WorkerThreadFactory threadFac = new WorkerThreadFactory();
	
	private void addWorkerThread(DelayTask task) {
		try {
			delayQueue.put(task);
			/*新创建一个工作线程,执行对DelayQueue的take操作*/
			threadFac.createWorkerThread().start();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	public void submit(Runnable r,long delay,long period) {
		// TODO Auto-generated method stub
		DelayTask task = taskFac.createDelayTask(r, delay, period);
		addWorkerThread(task);
	}
	
	@Override
	public void submit(Runnable r, long delay) {
		// TODO Auto-generated method stub
		DelayTask task = taskFac.createDelayTask(r, delay);
		addWorkerThread(task);
	}
	
	/*工作线程,每提交一个任务,分配一个工作线程来take此任务,工作线程从DelayQueue中取出任务后,再执行任务*/
	private class WorkerThread extends Thread{
		
		public WorkerThread() {
			
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			/*对DelayQueue执行take操作,获取成功后,将task的是否第一次执行置为false(先判断是否looptask),
			 * 如果是looptask,需要将此task再put到DelayQueue,执行完这些操作后,给task分配一个线程执行。*/
			DelayTask task = null;
			do {
				task = (DelayTask)delayQueue.poll();  /*返回值若为null,表示queue里面没有数据*/
				if( null != task ) {
					if( task instanceof LoopTask ) {
						((LoopTask) task).resetTask();
						addWorkerThread(task);
					}
					
					threadpool.execute(task.getTask());
				}
			}while(null == task);
		}
	}
	
	private class WorkerThreadFactory {
		public WorkerThread createWorkerThread() {
			return new WorkerThread();
		}
	}
}




/*用DelayQueue模拟了一个ScheduledExecutorService。
 * 要点:
 * 1、Delayed接口的两个方法的实现
 * 2、每个DelayTask配置一个工作线程,用来将DelayTask从DelayQueue中取出,执行,或者重设后执行
 * 3、LoopTask的处理,initDelay与period的区别处理
 * 4、getDelay方法,返回的是动态值,其单位与入参的TimeUnit匹配,具体匹配方式在方法内部实现
 * 
 * 思考:
 * 1、priorityQueue使用compareTo方法将DelayTask排序
 * 2、DelayQueue使用getDelay方法,根据返回值让工作线程delay,直到超时时间到
 * 3、如果将工作线程也交给线程池分配,是否可降低开销?
 * 4、工作线程与DelayTask线程能否合并?*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值