Java之手写异步任务

    为什么需要异步任务?有些代码可能影响程序性能,并且不需要实时同步执行,这部分代码就可以放到异步任务中,以减少响应时间。比如在用户操作软件的时候需要记录一些操作日志,频繁写入db的操作会影响用户体验。

实现思路: 首先创建一个AbstractQueue类,用于存放任务队列。然后创建一个AbstractAsynTask类,用于管理AbstractQueue队列。

下面是具体实现:

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: jack
 * @Description:抽象异步队列
 */
public abstract class AbstractQueue {

    private static Logger log = LoggerFactory.getLogger(AbstractQueue.class);

    //队列空闲时间  3分钟
    private static final int timeout = 3 * 60 * 1000 ;

    //当前任务大小
    private volatile AtomicInteger size = new AtomicInteger();

    //线程启动开关
    private boolean isRun = false;

    private volatile Queue queue = new ConcurrentLinkedQueue();

    //线程,用于遍历队列
    private volatile Thread thread = null;

    //最后执行时间
    private volatile long lastTime = System.currentTimeMillis();

    //队列名称
    public String queueName = "抽象队列";

    //线程结果汇总
    private volatile StringBuilder resultBuilder = new StringBuilder();

    //总数
    private volatile AtomicInteger total = new AtomicInteger();

    //成功数
    private volatile AtomicInteger success = new AtomicInteger();

    //失败数
    private volatile AtomicInteger fail = new AtomicInteger();

    public void add(Object dto) {
        queue.add(dto);
        size.incrementAndGet();
        total.incrementAndGet();
    }

    private void stop() {
        log.error("【" + queueName + "】,线程关闭");
        isRun = false;
        resultBuilder.append("总数:" + total.intValue() + ",成功数:" + success.intValue() + ",失败数:" + fail.intValue());
        log.error(resultBuilder.toString());
    }

    private void start() {
        log.error("【" + queueName + "】,线程开启");
        isRun = true;
        thread.start();

    }

    public int getSize() {
        return size.get();
    }

    public AbstractQueue(String queueName) {
        this.queueName = queueName;
        resultBuilder.append("【" + queueName + "】,执行汇总:").append("\r\n");

        thread = new Thread(() -> {
            while (isRun) {
                Object emailDto = null;
                try {
                    if (!queue.isEmpty()) {
                        lastTime = System.currentTimeMillis();
                        emailDto = queue.poll();
                        size.decrementAndGet();

                        task(emailDto);

                        success.incrementAndGet();
                    }

                    long currentTime = System.currentTimeMillis();
                    if ((currentTime - lastTime) >= timeout) {
                        stop();
                    } else {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    fail.incrementAndGet();
                }
            }
        });

        start();
    }

    abstract public void task(Object dto);

    public boolean isAlive() {
        return thread.isAlive() && isRun;
    }
} 
  
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @Author: jack
 * @Description:抽象异步任务
 */
public abstract class AbstractAsynTask {
    //每个队列最大容量
    public static final int max_capacity = 500;

    //队列列表
    public volatile List queueList =new ArrayList<>();

    public void add(Object dto){
        boolean isAdd = false;

        Iterator ite = queueList.iterator();
        while(ite.hasNext()){
            AbstractQueue queue = (AbstractQueue) ite.next();
            if(queue.getSize() >= max_capacity){
                continue;
            }

            if(!queue.isAlive()){
                ite.remove();
                queueList.add(createNewQueue());
            }

            queue.add(dto);
            isAdd = true;
            break;
        }

        if(!isAdd){
            AbstractQueue queue = doCreateNewQueue();
            queue.add(dto);
            queueList.add(queue);
        }
    }

    public AbstractQueue doCreateNewQueue(){
        return createNewQueue();
    }

    abstract public AbstractQueue createNewQueue();

    public int getQueueSize(){
        return queueList.size();
    }

}

  到这已经大功告成了,接下来写个具体实现,测试一下异步任务。

public class SendMsgQueue extends AbstractQueue {

    @Override
    public void task(Object dto) {
        try {
            System.out.println("【"+queueName+"】"+"sending content :"+dto);
            Thread.sleep(50);
            System.out.println("【"+queueName+"】"+"send finish...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public SendMsgQueue(String queueName){
        super(queueName);
    }
}
public class SendMsgAsynTask extends AbstractAsynTask {

    @Override
    public AbstractQueue createNewQueue() {
        return new SendMsgQueue("消息队列"+getQueueSize());
    }
}

然后是测试类

public class test {

    public static void main(String[] args) {
        SendMsgAsynTask task = new SendMsgAsynTask();
        for(int i=0;i<10000;i++){
            task.add("hello world");
        }
    }
}

执行后控制台部分输出如下

[ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列17】,线程开启
【消息队列16】sending content :hello world
【消息队列17】sending content :hello world

2020-04-03 09:39:56
[ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列18】,线程开启
【消息队列18】sending content :hello world

2020-04-03 09:39:56
[ERROR]-[Thread: main]-[com.recovery.www.task.asyn.AbstractQueue.start()]: 【消息队列19】,线程开启
【消息队列19】sending content :hello world
【消息队列0】send finish...
【消息队列1】send finish...
【消息队列2】send finish...

可以看到执行10000个任务总共开启了19个线程。这些任务在线程中串行执行

你可能感兴趣的:(java,queue,多线程,队列,thread)