与线程通信的模式

Pattern to communicate with a thread

我有一个包含 List 的 class OuterClass 并且有一个在 OuterClass 中启动的线程 ListWorker 添加了一些元素到列表中。基于对 OuterClass 的函数调用,它应该能够通知线程删除元素。最佳做法是什么?目的不是要有阻塞数据结构(无同步),因此要有一个线程在 List 上工作。

Class OuterClass {
    List<String> list = new ArrayList<String>();
    ListWorker worker = new ListWorker(list);

    deleteLastElement() {
        worker.setDeleteLastElement(true);
    }
}

工人

ListWorker implements Runnable {

private List<String> list;
private volatile boolean deleteLastElement;

public void setDeleteLastElement(boolean deleteLastElement) {
    this.deleteLastElement = deleteLastElement; 
}

public ListWorker(List<String> list) {
   this.list = list;
}

public void run() {
while(true) {
    //add random elements

    if(deleteLastElement) {
     //delete last element
     //set the boolean now to false
    }
  }
}

这是未经测试的,可能需要一些额外的异常处理,但大致就是这样:

ListWorker implements Runnable {

    private interface Command{
        void execute();
    }

private List<String> list;
private BlockingQueue<ListWorker.Command> work; // give it a Blocking Queue impl.
private volatile boolean bAddRandomElements;


public synchronized void deleteLastElement() {
     work.add( new Command(){
            @Override
            public void execute(){ /* delete Last Element of the list */ }
        } ); 
}

public synchronized void startAddingRandom() {
     work.add( new Command(){
            @Override
            public void execute(){ /* set switch bAddRandomElements */ }
        } ); 
}

public synchronized void stopAddingRandom() {
     work.add( new Command(){
            @Override
            public void execute(){ /* reset switch bAddRandomElements */ }
        } ); 
}

public synchronized void terminate() {
     work.add( new Command(){
            @Override
            public void execute(){ /* interrupt thread */ }
        } ); 
}


public ListWorker(List<String> list) {
   this.list = list;
}

public void run() {
    while(!Thread.interrupted()) {
       Command c = null;
       if( bAddRandomElements ){ 
           /* add random, assuming you add one random entry per iteration ... */
           c = work.poll( /*maybe specify timeout*/ ); // No command - just go on with it! We'll block in next iteration if bAddRandomElements is reset.
       }else{
           c = work.take(); // blocks until there is a command in queue.
       }

       if ( null != c ) c.execute();

    }
}