本文介绍一种采用线程交互模型,即主线程执行队列的Task,其他线程投递Task进入主线程的任务队列,投递方式类似于Win32 SDK的PostMessage和SendMessage方法,提供异步投递和同步投递。
首先我们需要一个BlockAndAwaitableQueue类,该类的功能是提供除执行Task线程外的其他线程的任务投递功能,该类包含一个任务列表,即存放待执行的Task。同时要考虑到多线程的同步问题,需要采用同步锁进行同步。同时要保证BlockAndAwaitableQueue的主执行线程在无Task可执行时不占用过多的系统资源需要实现一种monitor模型。即在没有Task可执行时,需要使该线程进入等待队列中,而在有Task投入进来时,需要唤醒Task列表中的等待队列中的当前执行线程。该模型有个限制,即所提交的Task不应占用过多的执行时间。
首先我们需要一个BlockAndAwaitableQueue类,该类的功能是提供除执行Task线程外的其他线程的任务投递功能,该类包含一个任务列表,即存放待执行的Task。同时要考虑到多线程的同步问题,需要采用同步锁进行同步。同时要保证BlockAndAwaitableQueue的主执行线程在无Task可执行时不占用过多的系统资源需要实现一种monitor模型。即在没有Task可执行时,需要使该线程进入等待队列中,而在有Task投入进来时,需要唤醒Task列表中的等待队列中的当前执行线程。该模型有个限制,即所提交的Task不应占用过多的执行时间。
- public class BlockAndAwaitableQueue{
- private ArrayList taskList = new ArrayList();
- private volatile boolean bStop = false;
- private volatile boolean bRunning = false;
- private Thread runningThread;
- Runnable finalTask = new Runnable()
- {
- public void run()
- {
- System.out.println("runningThread will exit.");
- synchronized (this) {
- bRunning = false;
- System.out.println("notify ...");
- synchronized (runningThread) {
- runningThread.notifyAll();
- }
- }
- System.out.println("runningThread exit.");
- }
- };
- public BlockAndAwaitableQueue()
- {
- }
- /*
- * This can be called by runningThread and other threads.
- * @param task The task wants to be executed asychronized.
- */
- public void addTask(Runnable task)
- {
- synchronized(taskList)
- {
- taskList.add(task);
- // notify
- taskList.notifyAll();
- }
- }
- /*
- * This can not be called by the runningThread
- */
- public void addTaskAndAwait(final Runnable task)
- {
- if(runningThread == Thread.currentThread())
- {
- System.out.println("This can not be called by the runningThread");
- return;
- }
- final Object latchObject = new Object();
- synchronized(latchObject)
- {
- addTask(new Runnable(){
- public void run()
- {
- task.run();
- synchronized(latchObject)
- {
- latchObject.notify();
- }
- }
- });
- try {
- latchObject.wait();
- } catch (InterruptedException e) {
- }
- }
- }
- public void stopInvocation()
- {
- bStop = true;
- addTask(finalTask);
- }
- public void stopInvocationAndAwait()
- {
- bStop = true;
- addTaskAndAwait(finalTask);
- }
- private void doInvocations()
- {
- synchronized(taskList)
- {
- while(taskList.size() == 0)
- {
- try {
- taskList.wait();
- } catch (InterruptedException e) {
- }
- }
- for(int i=0; i < taskList.size(); i++)
- {
- Runnable task = (Runnable)taskList.get(i);
- task.run();
- task = null;
- }
- // clear the task list
- taskList.clear();
- }
- }
- public void run()
- {
- synchronized (this) {
- while(bRunning)
- {
- try {
- System.out.println("await ...");
- synchronized (runningThread) {
- runningThread.wait();
- }
- System.out.println("await over");
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- bRunning = true;
- }
- runningThread = Thread.currentThread();
- bStop = false;
- while(!bStop)
- {
- doInvocations();
- }
- }
- public static void main(String[] args)
- {
- final BlockAndAwaitableQueue taskQueue = new BlockAndAwaitableQueue();
- new Thread(new Runnable(){
- public void run()
- {
- taskQueue.run();
- }
- }).start();
- new Thread(new Runnable(){
- public void run()
- {
- taskQueue.run();
- }
- }).start();
- new Thread(new Runnable(){
- public void run()
- {
- taskQueue.addTaskAndAwait(new Runnable(){
- public void run()
- {
- System.out.println("Task ID#1 has been executed.");
- }
- });
- System.out.println("After Task ID#1 has been executed.");
- }
- }).start();
- new Thread(new Runnable(){
- public void run()
- {
- taskQueue.addTask(new Runnable(){
- public void run()
- {
- System.out.println("Task ID#2 has been executed.");
- //stop the queue
- }
- });
- }
- }).start();
- new Thread(new Runnable(){
- public void run()
- {
- taskQueue.stopInvocationAndAwait();
- taskQueue.stopInvocationAndAwait();
- }
- }).start();
- }
- }