2015-08-21 2 views
1

Я работаю над веб-приложением, которое должно выполнять некоторые длительные задачи (задачи, которые занимают около 20 минут).MultiThreading Java - приостановка длительных задач из веб-приложения

Я хочу, чтобы они работали на параллельном потоке, чтобы пользователь мог продолжать работать над чем-то еще в веб-приложении во время выполнения задачи.

Предположим, что это класс, который выполняет задачу

public class TaskPerformer { 

    public void performTask(String[] taskParameters){ 

     // Long running task 

    } 

} 

Я создал класс резьбы, как этот

public class TaskThread extends Thread { 
    private TaskPerformer performer = new TaskPerformer(); 
    private String threadName; 

    public TaskThread(String name){ 
     this.threadName = name; 
    } 

    public void run(){ 
     String[] params = {"Param1","Param2","Param3"}; 
     this.performer.performTask(params); // This might take 15-20 mins to complete 
     System.out.println("Task completed successfully"); 
    } 
} 

Теперь в моем веб-приложение, я создаю новый поток, основанный на этом один, и запустите его, чтобы задача выполнялась в отдельном потоке. Это позволяет моему пользователю продолжить некоторые другие работы на моем веб-сервере.

Теперь, я хотел бы добавить кнопку на моем графическом интерфейсе, чтобы приостановить и остановить эту задачу.

Будучи новым для многопоточности, я прочитал и понял, что не могу использовать suspend() или resume(), поскольку они обесцениваются. Так что в моих сеансов методом проб и ошибок, я пытался реализовать простую pauseable нить, как показано ниже:

public void run(){ 
    for(int i=10;i>0;i--){ 
     checkForPaused(); 
     System.out.println(this.threadName + " -- Counter -- " + i); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

я реализовал метод checkForPaused() для проверки булевой флаг, чтобы проверить, если мне нужно приостановить поток и сделать wait() для статической переменной до тех пор, пока логическое значение не будет изменено.

(Я получил эту идею с этого поста How to Pause and Resume a Thread in Java from another Thread)

Но, в западню в растворе, является то, что я должен назвать checkForPaused() в каждой итерации моего цикла. Это означает, что я не могу приостановить длинную задачу, которую я собираюсь начать, потому что я делаю это только один раз в потоке.

Может кто-нибудь предложить идею, как я могу это реализовать?

+0

Вы ча n запустите фоновый процесс, который вы можете убить в любое время. –

+0

Поместите публичный volatile boolean в поток, называемый паузой. В своей задаче неоднократно проверяйте приостановленное логическое и сон, если он приостановлен. – bhspencer

+0

@PeterLawrey Спасибо, но не могли бы вы объяснить, как я могу это сделать? любая начальная точка ссылки? – sriramsridharan

ответ

2

Если вы не назовете checkForPaused несколько раз, нет возможности приостановить поток извне, не рискуя противоречивым поведением. Причина, по которой suspend() и resume() устарели, - это то, что поток может быть остановлен в тот момент, когда данные находятся в несогласованном состоянии, поэтому единственный способ сделать это право - сообщить потоку, что он должен быть приостановлен , Но как и когда это произойдет, должно быть реализовано только в самом потоке (потому что только поток знает, когда данные находятся в согласованном состоянии).

Возможный вспомогательный класс:

public class Helper { 
    private volatile boolean flag; 

    public synchronized void pause() { 
     flag = true; 
    } 

    public synchronized void isPaused() { 
     while(flag) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       // Set to false, so the thread can be interrupted (!= paused) 
       flag = false; 
      } 
     } 
    } 

    public synchronized void continue() { 
     flag = false; 
     notify(); 
    } 
} 

Держите ссылку на объект вашего метода работника и в любом месте, где вам нужно сделать паузу/возобновлять нить. Вызов isPaused() в вашем рабочем методе.

+0

То, что вы говорите, означает, что в моем методе executeTask() я должен постоянно проверять флаг через определенные промежутки времени, чтобы приостановить протектор. Если мое понимание правильное, то как мне получить значение флага для моего объекта TaskPerformer, поскольку он уже инициализирован, и у меня есть метод, который выполняется в настоящее время. Вопрос номер два будет, нет ли другого пути ??? Как это делают другие программы? например, IDE, например Eclipse. – sriramsridharan

+0

Или, если я могу справиться с проблемами, с которыми сталкиваюсь, когда мой поток приостанавливается, когда данные находятся в несогласованном состоянии, могу ли я использовать устаревшие методы? – sriramsridharan

+0

1. Если существует способ обхода устаревшего метода, не используйте его. 2. Просто используйте параметр конструктора, чтобы дать TaskPerformer ссылку на ссылку Helper. –