Java 延时队列(延时到账/延时执行)

功能实现:延迟一段时间再执行一个操作

参考文章:https://www.cnblogs.com/barrywxx/p/8525907.html

1. DelayOrderQueueManager

package cn.zykj.delqueue;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;  

/** 
 * 延时队列管理类,用来添加任务、执行任务 
 *  
 */  
public class DelayOrderQueueManager {  
	private final static int DEFAULT_THREAD_NUM = 5;  
	private static int thread_num = DEFAULT_THREAD_NUM;  
	// 固定大小线程池  
	private ExecutorService executor;  
	// 守护线程  
	private Thread daemonThread;  
	// 延时队列  
	private DelayQueue> delayQueue;  
	//    private static final AtomicLong atomic = new AtomicLong(0);  
	//    private final long n = 1;  
	private static DelayOrderQueueManager instance = new DelayOrderQueueManager();  

	private DelayOrderQueueManager() {  
		executor = Executors.newFixedThreadPool(thread_num);  
		delayQueue = new DelayQueue<>();  
		init();  
	}  

	public static DelayOrderQueueManager getInstance() {  
		return instance;  
	}  

	/** 
	 * 初始化 
	 */  
	public void init() {  
		daemonThread = new Thread(execute());
		daemonThread.setName("DelayQueueMonitor");  
		daemonThread.start();  
	}  

	private Runnable execute() {  
		Runnable run = new Runnable() {
			@Override
			public void run() {
				while (true) {  
					//		            Map map = Thread.getAllStackTraces();  
					//		            System.out.println("当前存活线程数量:" + map.size());  
					//		            int taskNum = delayQueue.size();  
					//		            System.out.println("当前延时任务数量:" + taskNum);  
					try {  
						// 从延时队列中获取任务  
						DelayOrderTask delayOrderTask = delayQueue.take();  
						if (delayOrderTask != null) {  
							Runnable task = delayOrderTask.getTask();  
							if (null == task) {  
								continue;  
							}  
							// 提交到线程池执行task  
							executor.execute(task);  
						}  
					} catch (Exception e) {  
						e.printStackTrace();  
					}  
				} 
			}
		}; 
		return run;
	}  

	/** 
	 * 添加任务 
	 *  
	 * @param task 
	 * @param time 
	 *            延时时间 
	 * @param unit 
	 *            时间单位 
	 */  
	public void put(Runnable task, long time, TimeUnit unit) {  
		// 获取延时时间  
		long timeout = TimeUnit.NANOSECONDS.convert(time, unit);  
		// 将任务封装成实现Delayed接口的消息体  
		DelayOrderTask delayOrder = new DelayOrderTask<>(timeout, task);  
		// 将消息体放到延时队列中  
		delayQueue.put(delayOrder);  
	}  

	/** 
	 * 删除任务 
	 *  
	 * @param task 
	 * @return 
	 */  
	public boolean removeTask(DelayOrderTask task) {  
		return delayQueue.remove(task);  
	}  
}

2. DelayOrderTask

package cn.zykj.delqueue;

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

/** 
 * 延时队列中的消息体将任务封装为消息体 
 *  
 */  
public class DelayOrderTask implements Delayed {  
	private final long time;  
	private final T task; // 任务类,也就是之前定义的任务类  

	/** 
	 * @param timeout 
	 *            超时时间(秒) 
	 * @param task 
	 *            任务 
	 */  
	public DelayOrderTask(long timeout, T task) {  
		this.time = System.nanoTime() + timeout;  
		this.task = task;  
	}  

	@Override  
	public int compareTo(Delayed o) {  
		DelayOrderTask other = (DelayOrderTask) o;  
		long diff = time - other.time;  
		if (diff > 0) {  
			return 1;  
		} else if (diff < 0) {  
			return -1;  
		} else {  
			return 0;  
		}  
	}  

	@Override  
	public long getDelay(TimeUnit unit) {  
		return unit.convert(this.time - System.nanoTime(), TimeUnit.NANOSECONDS);  
	}  

	@Override  
	public int hashCode() {  
		return task.hashCode();  
	}  

	public T getTask() {  
		return task;  
	}  
}

3. DelayOrderWorker(逻辑处理类)

spring 框架中如果需要调用 service、mapper 层则需手动 getBean 或当成参数传递进来,才可正常使用,否则报空指针异常

package cn.zykj.delqueue;

import java.math.BigDecimal;

import cn.zykj.dao.TransactionrecordMapper;
import cn.zykj.dao.WallettableMapper;
import cn.zykj.service.impl.WallettableServiceImpl;

/** 
 * 延时执行队列(平台内延时到账)
 * 
 */  
public class DelayOrderWorker implements Runnable {
	
	// 变量根据需求定义
	public int memberid = 0;
	public String virtualcurrencyname = "";
	public String sourceaddress = "";
	public BigDecimal transactionnumber = BigDecimal.ZERO;
	public int transactionfundstype = 0;
	
	private WallettableServiceImpl wallettableServiceImpl;
	private WallettableMapper wallettableMapper; 
	private TransactionrecordMapper transactionrecordMapper;
	
	/**
	 * 创建延时任务 (构造函数参数根据自己需求创建)
	 * spring中使用service或mapper时手动getBean或传递进来
	 * @param memberid 会员ID
	 * @param virtualcurrencyname 币种类型
	 * @param sourceaddress 来源地址
	 * @param transactionnumber 交易数量
	 * @param transactionfundstype 交易资金类型
	 */
	public DelayOrderWorker(int memberid, String virtualcurrencyname, String sourceaddress,
			BigDecimal transactionnumber, int transactionfundstype,
			WallettableServiceImpl wallettableServiceImpl, WallettableMapper wallettableMapper, TransactionrecordMapper transactionrecordMapper){
		
		System.out.println("<----------平台内转账处理中>目标=》会员ID="+memberid+">币种类型="+virtualcurrencyname
				+">来源="+sourceaddress+">数量="+transactionnumber+">资金类型="+transactionfundstype+"---------->");
		
		this.memberid = memberid;
		this.virtualcurrencyname = virtualcurrencyname;
		this.sourceaddress = sourceaddress;
		this.transactionnumber = transactionnumber;
		this.transactionfundstype = transactionfundstype;
		
		this.wallettableServiceImpl = wallettableServiceImpl;
		this.wallettableMapper = wallettableMapper;
		this.transactionrecordMapper = transactionrecordMapper;
	}
	
    @Override  
    public void run() {  
    	// 逻辑处理
    	wallettableServiceImpl.app_transfer_in(memberid, virtualcurrencyname, sourceaddress, transactionnumber, transactionfundstype, wallettableMapper, transactionrecordMapper);
    }  
}

使用方法:

你可能感兴趣的:(Java,延时队列,Java,延时执行)