博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【代码积累】Simulate schedule service
阅读量:4099 次
发布时间:2019-05-25

本文共 5380 字,大约阅读时间需要 17 分钟。

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
delayQueue = new DelayQueue
(); 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线程能否合并?*/
 

转载地址:http://tthii.baihongyu.com/

你可能感兴趣的文章
【go链表排序】常数级空间复杂度、nlogn时间复杂度
查看>>
秒杀系统的艺术【内有库存问题解决方法】
查看>>
go语言错题集(坑)【一】
查看>>
go语言错题集(坑)【二】
查看>>
go语言错题集(坑)【三】
查看>>
go简单协程池实现
查看>>
python装饰器与偏函数
查看>>
图解传说中的HTTP协议
查看>>
go闭包
查看>>
go反射
查看>>
部署超简单的 Golong 分布式 WebSocket 微服务
查看>>
go资料
查看>>
go mod 无法下载依赖问题
查看>>
mysql source插入数据乱码
查看>>
go 解析csr参数(完整)
查看>>
golang日志框架之logrus
查看>>
es修改密码
查看>>
go 协程池使用提示
查看>>
go 生成邀请码,可逆
查看>>
Go 高级并发
查看>>