Проблема с потоком Java - PullRequest
       5

Проблема с потоком Java

0 голосов
/ 16 апреля 2011

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

Проблема, с которой я столкнулся, состоит в том, что, как только новый поток запущен, я не могу переключиться обратно в GUI, пока он не будет завершен, и так как поток будет продолжать работать, пока я не скажу емустоп, я не могу выйти из бесконечного цикла.Могу ли я исправить это, поместив графический интерфейс в отдельный поток, чтобы оба потока запускались одновременно?И если так, как бы я поступил так внутри 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;
}

}

Ответы [ 5 ]

3 голосов
/ 16 апреля 2011

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

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

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

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

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

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

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

2 голосов
/ 16 апреля 2011

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

См. Описание "EDT", потока графического интерфейса Swing: 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 () и другие, чтобы начать работу ...

2 голосов
/ 16 апреля 2011

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

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

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

РЕДАКТИРОВАТЬ: добавлено больше кода. вам нужно thread.start() не thread.run(). Метод start фактически запускает выполнение нового потока (который затем вызывает метод run ()). Когда вы вызываете метод run () напрямую, это просто обычный вызов метода, который выполняется в вызывающем потоке (GUI), поэтому пользовательский интерфейс блокируется.

1 голос
/ 16 апреля 2011

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

Из того, что я прочитал, я могу предложить вам реализовать своего рода игровой цикл.Поскольку я понимаю, вы захотите смоделировать трафик и представить его пользователю.Тогда такой игровой цикл будет, на каждой своей итерации, сначала выполнять все вычисления и обновлять ваши объекты, наконец отображая новое состояние на экране.Это непростая задача, и я боюсь, что вам следует ознакомиться с параллелизмом и синхронизацией кода в 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: из кода, который я наблюдаю, вы прекрасно создаете поток, но вы должны запустить его, используя метод запуска не запущенного потока.---> почему это объясняет @ Брэд.

Удачи, Боро.

1 голос
/ 16 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...