面试官提出一个问题:设计一个异步执行的队列。我的第一想法是采用阻塞队列,提供向阻塞队列中添加任务的方法,提供启动任务队列中任务的方法,当时的思路比较模糊,在这里写一下。在代码中虽然使用了阻塞队列,但并没有使用阻塞队列的特性。基本上实现了面试官所要求的功能,代码如下
public class AsyncRunnableQueue {
private static class AsyncRunnableQueueHolder{
private static final AsyncRunnableQueue INSTANCE = new AsyncRunnableQueue();
}
//维护一个阻塞队列
LinkedBlockingQueue<Runnable> linkedBlockingQueue;
//串行执行线程
Thread thread;
//并行执行线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(12);
//停止标志
boolean isStop;
private AsyncRunnableQueue(){
linkedBlockingQueue = new LinkedBlockingQueue<>();
}
//单例模式维护
public static final AsyncRunnableQueue getInstance(){
return AsyncRunnableQueueHolder.INSTANCE;
}
public void addRunnable(Runnable runnable){
if(linkedBlockingQueue != null){
linkedBlockingQueue.offer(runnable);
}
}
/**
* 串行执行所有Runnable
*/
public void runAllTaskSerial() {
isStop = false;
if (thread == null) {
thread = new Thread(new Runnable() {
@Override
public void run() {
while (!isStop && linkedBlockingQueue.peek() != null) {
System.out.println("Serial thread name:"+Thread.currentThread().getName());
Runnable runnable = linkedBlockingQueue.poll();
runnable.run();
}
}
});
}
if (!isStop) {
thread.start();
}
}
/**
* 并行执行runnable
* 串行执行中所有的runnable均在一个线程中串行执行,若runnable是耗时任务,则需要开启多个线程并行执行
* 这里我们使用线程池
*/
public void runTaskParallel(){
isStop = false;
while(!isStop && linkedBlockingQueue.peek() != null){
if(fixedThreadPool != null){
fixedThreadPool.execute(linkedBlockingQueue.poll());
}
}
}
public void stop(){
isStop = true;
}
}
测试代码:
public class AsyncRunnableQueueTest {
public static void main(String[] args) {
AsyncRunnableQueue queue = AsyncRunnableQueue.getInstance();
queue.addRunnable(new Runnable() {
@Override
public void run() {
System.out.println("runnable 1 currentThread:"+Thread.currentThread().getName());
}
});
queue.addRunnable(new Runnable() {
@Override
public void run() {
System.out.println("runnable 2 currentThread:"+Thread.currentThread().getName());
}
});
queue.addRunnable(new Runnable() {
@Override
public void run() {
System.out.println("runnable 3 currentThread:"+Thread.currentThread().getName());
}
});
// queue.runAllTaskSerial();
queue.runTaskParallel();
}
}
结果:
并行执行结果:
runnable 1 currentThread:pool-1-thread-1
runnable 2 currentThread:pool-1-thread-2
runnable 3 currentThread:pool-1-thread-3
可以看到,三个runnable是在三个不同的线程中跑的
串行执行结果:
Serial thread name:Thread-0
runnable 1 currentThread:Thread-0
Serial thread name:Thread-0
runnable 2 currentThread:Thread-0
Serial thread name:Thread-0
runnable 3 currentThread:Thread-0
可以看到,三个runnable是在同一个线程中串行执行
有兴趣的同学可以一起讨论