2011-04-15 2 views
0

Я работаю над приложением на Java, которое требуется обновлять его результаты каждую секунду до его остановки. В течение 30 секунд он будет вызывать определенный набор методов каждую секунду, затем другой набор в течение следующих 30 секунд, затем первый набор снова и так далее. Поскольку я хочу иметь возможность останавливать и перезапускать вычисления, которые выполняются в фоновом режиме всякий раз, когда я хочу, я создал графический интерфейс и пару кнопок для запуска и остановки нового потока, а также средство для отображения результатов каждую секунду.Проблема с потоком Java

Проблема, с которой я столкнулся, заключается в том, что после запуска нового потока я не могу вернуться к графическому интерфейсу до тех пор, пока он не будет завершен, и поскольку поток будет продолжаться, пока я не остановлю его, я в конечном итоге не имея возможности выйти из бесконечного цикла. Могу ли я исправить это, поместив GUI в собственный поток, чтобы оба потока запускались одновременно? И если да, то как я буду делать это изнутри графического интерфейса?

Я работаю с несколькими классами, поэтому я не хочу публиковать неуместные материалы.

public class GUI extends javax.swing.JFrame implements Runnable{ 
    Graphics g; 
    Threads thread = new Threads(); 
    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     thread.run() 
    } 
    [..] 
    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     thread.stop() 
    } 
} 
public class Threads implements Runnable{ 
boolean opened=false; 
road first = new road(); 
public void run() { 
    opened=true; 
    first.standardInitialization(); 
    while(opened){ 
     for(int i=0; i<30 && opened; i++){ 
      try { 
       first.redLightAction(); 
       System.out.println("cars: " + first.firstLight.cars); 
       Thread.sleep(1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Threads.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
     for(int i=0; i<30 && opened; i++){ 
      try { 
       first.greenLightAction(); 
       second.greenLightAction(); 
       System.out.println("cars: " + first.firstLight.cars); 
       Thread.sleep(1000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Threads.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
} 
public void stop(){ 
    opened=false; 
} 

} 
+0

Пожалуйста, разместите соответствующий код. – MByD

+0

Почтовый индекс. Если вы действительно создали новый поток для выполнения работы, он не должен влиять на поток графического интерфейса. –

+0

Статья, которая ответит на ваш вопрос и даст вам решение, которое поможет вам: [параллелизм в swing] (http://download.oracle.com/javase/tutorial/uiswing/concurrency/index.html) –

ответ

3

Да, ваш графический интерфейс должен быть в отдельной теме.

Вы не используете Thread. Вы используете специальный класс, который реализует Runnable. Runnable! = Thread. Вы хотите сделать это вместо того, чтобы:

Thread thread = new Thread(new Threads()); 

Если вы хотите, чтобы запустить его, используйте

thread.start(); // not thread.run()!! 

Обратите внимание, что я передаю в вашей Runnable к реальному Thread. Я бы предложил переименовать ваш класс Threads в нечто более конкретное.

Итак, как вы его устанавливаете сейчас, вы просто запускаете Runnable в том же потоке, что и ваш графический интерфейс. С приведенным выше кодом вы создадите новый поток для выполнения.

+0

Предполагается имитировать пересечение двух улиц. Каждую секунду, когда светофор красный, случайное количество автомобилей ждет зеленый свет. Каждую секунду светофор зеленый, отходит количество автомобилей. Я должен следить за количеством автомобилей на каждом светофоре. – Skates

+0

Я не забочусь о бизнес-логике, я хочу видеть ваш фактический код того, как вы управляете потоками. Если ваш GUI блокируется, когда выполняется этот другой поток, вы либо arent, используя потоки правильно, либо другой поток каким-то образом блокирует ваш графический интерфейс (общий ресурс или что-то еще). – Brad

+0

Я разместил код, относящийся к вопросам, которые у меня были, не могли бы вы посмотреть? – Skates

2

Графический интерфейс обновляется по теме «Диспетчер событий». Поскольку у вас есть невосприимчивый пользовательский интерфейс, поток EDT не выполняет никакой работы. Это может быть:

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

Вы не можете запустить GUI в другом потоке - качание должно выполняться в потоке, создаваемом системой - Thread Dispatch Thread.

EDIT: добавлен еще код. вам нужно thread.start() не thread.run(). Метод start - тот, который фактически вызывает запуск нового потока (который затем вызывает метод run()). Когда вы вызываете метод run() напрямую, это обычный вызов метода и выполняется в потоке вызывающего (GUI), поэтому пользовательский интерфейс блокируется.

+0

Я уверен, что это первый вариант. Мой поток создается GUI, я бы предположил, что это означает, что он не будет запускаться одновременно с потоком GUI. Как я могу это исправить? – Skates

2

Да, любые не-gui-activites (особенно длительные задачи) должны запускаться на новом потоке.

Смотрите описание «EDT», GUI поток Свинга: http://en.wikipedia.org/wiki/Event_dispatching_thread

Вы можете использовать статические методы SwingUtilities' для облегчения переключения между EDT и другими нитями ... http://download.oracle.com/javase/6/docs/api/javax/swing/SwingUtilities.html

См invokeLater (Runnable), isEventDispatchThread(), и другие, чтобы вы начали ...

1

Качели НЕ поточно-. Качайте, используя что-то, называемое «Диспетчер событий» (посмотрите сообщение mdma для быстрого введения), и вы можете найти хороший учебник here. Swing не предназначался для работы с потоками, но вы можете моделировать почти все, что вы можете делать с потоками, с Thread Dispatch Thread, за исключением (большая точка здесь), это не будет одновременным.

1

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

Из того, что я читаю, я могу предложить вам реализовать своего рода игровой цикл. Поскольку я понимаю, что вы хотите имитировать трафик и представить его пользователю. Тогда такой игровой цикл будет, каждая его итерация, сначала выполнить все вычисления и обновить ваши объекты, наконец, отображая новое состояние на экране. Это не простая задача, и я боюсь, что вам стоит ознакомиться с параллелизмом и синхронизацией кода на Java.

public void run() 
{ 
    long startTime = System.currentTimeMillis(); 
    long currTime = startTime; 
    isRunning = true; 

    while(isRunning) 
    { 
     long elapsedTime = System.currentTimeMillis() - currTime; 
     currTime += elapsedTime; 
     update(elapsedTime); 
     gameRender(); 
     paintScreen(); 
     try 
     { 
      Thread.sleep(1000); 
     }catch(InterruptedException ex) 
     { 
      Logger.getLogger(GamePlayPanel.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 

Вы бы скелет, как один из приведенных выше в своем классе, который реализует Runnable, то вы создаете нить, придав ему свой класс в качестве параметра, наконец, вы начинаете его.

Подробнее о создании игры можно найти http://www.brackeen.com/ парень опубликовал фантастическую книгу об играх на Java, очень рекомендуется.

EDIT1: Из кода, который я наблюдаю, вы создаете Thread отлично, но вы должны запустить его, используя метод запуска Thread, который не запускается. ---> почему объясняется @Brad.

Удачи, Боро.

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