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<Object> 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<AbstractQueue> 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 import java.util.concurrent.*; public class ThreadPool { private final BlockingQueue<Runnable> taskQueue; private final Thread[] threads; public ThreadPool(int numThreads, int queueSize) { taskQueue = new ArrayBlockingQueue<>(queueSize); threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { threads[i] = new Thread(() -> { while (true) { try { Runnable task = taskQueue.take(); task.run(); } catch (InterruptedException e) { break; } } }); threads[i].start(); } } public void execute(Runnable task) throws InterruptedException { taskQueue.put(task); } public void shutdown() throws InterruptedException { for (Thread thread : threads) { thread.interrupt(); } for (Thread thread : threads) { thread.join(); } } } ``` 使用示例: ```java ThreadPool threadPool = new ThreadPool(10, 100); for (int i = 0; i < 50; i++) { final int j = i; threadPool.execute(() -> { System.out.println("Task " + j + " executed by " + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } threadPool.shutdown(); ``` 这个线程池使用了Java标准库中的BlockingQueueThread,允许您提交任务异步执行。您可以根据需要调整线程池的大小和任务队列的大小。注意在使用完线程池后需要调用shutdown()方法关闭线程池。接下来,我们可以将线程池封装为异步执行器: ```java import java.util.concurrent.*; public class AsyncExecutor { private final ThreadPool threadPool; public AsyncExecutor(int numThreads, int queueSize) { threadPool = new ThreadPool(numThreads, queueSize); } public void execute(Runnable task) throws InterruptedException { threadPool.execute(task); } public void shutdown() throws InterruptedException { threadPool.shutdown(); } } ``` 这个异步执行器使用我们手写的线程池,允许您提交任务异步执行。您可以根据需要调整线程池的大小和任务队列的大小。注意在使用完异步执行器后需要调用shutdown()方法关闭线程池。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值