0

У меня есть класс OuterClass, содержащего List и есть поток ListWorker, который запускается в OuterClass, что добавление некоторых элементов в список. Основываясь на вызове функции на OuterClass, он должен иметь возможность информировать поток об удалении элементов. Какова наилучшая практика? Цель состоит в том, чтобы не иметь блокирующую структуру данных (без синхронизации) и, следовательно, иметь один поток в списке.шаблона для взаимодействия с резьбой

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

Может быть, вы можете добавить Commandobject к «workqueue» из wokerThread? Просто настройка булевых кажется мне нестабильной. – Fildor

+0

@Fildor вы можете подробно остановиться на CommandObject? – user592748

+0

Подумайте об этом, как кучу файлов на рабочем столе. Люди приходят и ставят свои Задачи поверх кучи. Работник берет верх и работает на нем ... Люди (= другие темы) не будут заблокированы, но им, возможно, придется ждать, пока их изменения вступят в силу. Вам это нужно? Вы могли бы даже использовать блокирующую очередь, тогда вам нить даже не нужно ждать от спины ... – Fildor

ответ

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

    } 
} 
+0

это потрясающе. Теперь команды могут быть выполнены в том порядке, в котором они вызывают, и не будут пропущены, если несколько потоков попытаются установить значения. Благодаря! – user592748

Смежные вопросы