面試官提出一個問題:設計一個異步執行的隊列。我的第一想法是採用阻塞隊列,提供向阻塞隊列中添加任務的方法,提供啓動任務隊列中任務的方法,當時的思路比較模糊,在這裏寫一下。在代碼中雖然使用了阻塞隊列,但並沒有使用阻塞隊列的特性。基本上實現了面試官所要求的功能,代碼如下
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是在同一個線程中串行執行
有興趣的同學可以一起討論