2013-03-15 3 views
1

В моем проекте на java swing есть 2 кнопки (начало/остановка) для подсчета.java thread not interrupt при запуске большого количества потоков

Когда я нажимаю кнопку «Пуск». Существует один поток (Thread-0), затем нажмите кнопку остановки «Thread-0», но при многократном нажатии кнопки запуска. существует много потоков, таких как Thread-5, Thread-6, .. Thread-10 работает.

Задача: Если щелчок начинается, а затем прекращается подсчет, это нормально. но нажимать начать много раз, это неверный подсчет.

кнопка запуска

private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {   
    start(); 
    btnStart.setEnabled(false); 
    btnStop.setEnabled(true); 
} 

кнопка остановки

private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {    
    isEnable = false; 
    btnStop.setEnabled(false); 
    btnStart.setEnabled(true); 
}  

начало() метод:

isEnable = true; 
Thread refreshPlan = new Thread() { 
    @Override 
    public void run() { 
     while(isEnable) { 
      try { 
       sleep(CYCLE_TIME * 1000); 
       PLAN += 1; 
       planValue.setText(String.valueOf(PLAN)); 
      } catch (InterruptedException ex) { 
       //ignore 
      } 
     } 
    }; 
    }; 
    refreshPlan.start(); 

Может Я запускаю только один поток при многократном нажатии кнопки запуска? любое предложение? Благодарю.

извините за мой плохой английский.

+0

для получения более точной информации о более раннем размещении [SSCCE] (http://sscce.org/), short, runnable, compilable, однако вопрос о Concurency in Swing ответил – mKorbel

ответ

5

Есть четыре важных проблем здесь:

  • Если только isEnable объявлен как летучее переменной, там нет убедитесь, что запись из одной нити будет видна в другом потоке
  • Аналогично ваш доступ к счетчику PLAN (который плохо назван - пожалуйста, следуйте Соглашения о присвоении имен Java) является небезопасным. Вы можете рассмотреть возможность использования AtomicInteger.
  • Вы вносите изменения в пользовательский интерфейс из дополнительной темы. Вы не можете этого сделать - в Swing (и большинстве пользовательских интерфейсов) весь доступ к компонентам пользовательского интерфейса должен выполняться в потоке, отвечающем за этот интерфейс. См. Swing concurrency tutorial для более подробной информации.
  • Потому что вы только проверяете isEnabled один раз в секунду, можно было бы остановить и запустить несколько потоков за это время ... приводя к тому, что сразу несколько потоков будут активны. Это может помешать вашему подсчету.

Возможно, вам будет полезно использовать javax.swing.Timer, который срабатывает один раз в секунду и просто проверяет, предназначено ли оно что-либо делать. Таким образом все может быть в потоке пользовательского интерфейса.

+0

@Phonbopit use [SwingWorker] (http://stackoverflow.com/a/15166242/714968), Swing Timer предназначен для задержки, управляемый цикл контуров, а не для каскадирования рабочих потоков в Swing – mKorbel

+0

+1, но исключая Swing Timer – mKorbel

+0

@mKorbel: Что вы подразумеваете под «каскадом рабочих потоков»? Я предлагал один бесконечный цикл, эффективно - каждую секунду, он * либо * увеличивает счетчик, либо нет, основываясь на состоянии. Я предпочел бы сделать это, чем использовать дополнительные потоки с SwingWorker. Сохранение всего в одном потоке уменьшает всевозможные возможности для ошибок. –

-1

метод запуска создает экземпляр новой темы(), поэтому каждый раз, когда вы нажимаете на нее, она вносит новую жизнь в жизнь.

объявить Thread refreshPlan переменная класса, то в методе запуска поместить весь код в этой проверке

if(refreshPlan == null || !refreshPlan.isAlive()){ 
//ur existing code to instantiate new thread. 
} 
+0

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

+0

хорошо, я не думаю, что есть достаточно запаздывания там в проверке и его времени, кроме того, такие случаи краев могут происходить где угодно в условных потоках. – Ankit

+0

Нет, условия гонки, подобные этому, происходят только тогда, когда вы не учитываете их. 'Thread.isAlive()' должен почти * всегда * использоваться для диагностических целей, а не для того, чтобы логика запускала другой поток. –

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