与线程通信的模式

时间:2015-02-25 12:14:54

标签: java multithreading design-patterns synchronization nonblocking

我有一个包含OuterClass的类List,并且在ListWorker中启动了一个线程OuterClass,它将一些元素添加到列表中。基于对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
    }
  }
}

1 个答案:

答案 0 :(得分:1)

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

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();

    }
}