【问题标题】:Pattern to communicate with a thread与线程通信的模式
【发布时间】:2015-02-25 12:14:54
【问题描述】:

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

【问题讨论】:

  • 也许您可以将 Commandobject 添加到wokerThread 的“工作队列”中?仅仅设置一个布尔值对我来说似乎真的很不稳定。
  • @Fildor 你能详细说明 CommandObject 吗?
  • 把它想象成工人办公桌上的一堆文件。人们来把他们的任务放在最上面。工人采取最底层的工作......人们(=其他线程)不会被阻塞,但他们可能必须等待他们的变更请求生效。这是你想要的吗?你甚至可以使用阻塞队列,然后你的线程甚至不需要旋转等待......
  • @Fildor 完全正确。这就是我想要的。我有一个所有线程都与之交互的缓冲区,它是线程安全且无锁的。我只有一个线程来处理这些事情。那是工作线程。命令对象是否适用于此用例?
  • 当然。我没有时间写一个完整的答案。如果明天还没有答案,我会写一些东西。

标签: java multithreading design-patterns synchronization nonblocking


【解决方案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();

    }
}

【讨论】:

  • 这太棒了。现在命令可以按照它们被调用的顺序执行,并且如果多个线程尝试设置值不会错过。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-10
  • 1970-01-01
  • 2012-04-20
  • 2013-07-21
  • 2013-10-09
相关资源
最近更新 更多