Java: Вызов метода, вызывающего сам, без замораживания? - PullRequest
3 голосов
/ 23 сентября 2011

Так что это действительно сложно, мне потребовалось некоторое время, чтобы понять, что на самом деле происходит. Надеюсь, вы понимаете это лучше меня.

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

Когда вызывается этот метод, я вызываю другой метод в объекте под названием «Менеджер». Затем метод в менеджере вызывает другой метод из класса «Core». Этот метод в Core устанавливает локальную переменную, а затем вызывает другой метод в Core, который сам вызывается.

Проблема в том, что, поскольку он вызывает себя сам, он никогда не останавливается, верно? И поскольку он никогда не останавливается, ничего не возвращается к первому методу в Core. И поскольку в этот метод ничего не возвращается, в Manager также ничего не возвращается. И поскольку этот метод никогда не вызывается, класс GUI никогда не получает ответ, что оставляет GUI замороженным.

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

Спасибо!

EDIT:

Я забыл упомянуть, что класс Core является потоком.

Ответы [ 6 ]

3 голосов
/ 23 сентября 2011

Самопризыв называется рекурсией. Это мощная техника, но она может привести к бесконечным циклам (зависания), если вы не будете осторожны. Вы должны убедиться, что в каждой рекурсии (то есть каждый раз, когда метод вызывается сам) что-то меняется в сторону завершающего состояния. Например, у вас может быть число, которое гарантированно уменьшает каждую рекурсию, и в качестве условия выхода ваш номер отрицательный. Другой пример - вы рекурсивно «съедаете» некоторую структуру данных, скажем, строку, пока ничего не останется. Обычно это «что-то, что изменяется к завершающему состоянию», передается методу в качестве аргумента. Ваш рекурсивный метод должен начинаться с проверки: мой аргумент в состоянии завершения? Если да, прекратите, если нет, сотворите магию.

Во-вторых, с Swing вы должны быть осторожны, чтобы не нарушать его архитектуру. Это на самом деле не MVC, а скорее двухслойный фреймворк. Если вам интересно, как использовать Swing, я рекомендую ознакомиться с шаблонами проектирования, такими как MVC.

3 голосов
/ 23 сентября 2011

Ваш длительный процесс препятствует продолжению основного потока Swing, EDT или потока диспетчеризации событий, и это сделает ваш GUI полностью не отвечающим.Решение состоит в том, чтобы выполнить любой длительный процесс в фоновом потоке, например, созданный объектом SwingWorker.Пожалуйста, проверьте ссылку под названием Параллельность в Swing , чтобы узнать больше об использовании объектов SwingWorker.

2 голосов
/ 23 сентября 2011

У вас есть ряд проблем.

1) Ваша рекурсивная функция нуждается в условии выхода.Итак, что-то вроде

public int imRecursive(int arg) {
   if (arg > 100) return;
   imRecursive(arg++);    
}

в этом примере, imRecursive не вызывается снова и снова, оно останавливается, когда arg достигает 100.

2) С приложением свингаВ основном потоке диспетчеризации событий должен выполняться только код, связанный с GUI.Если ваш рекурсивный метод долго выполняется, вы должны использовать SwingWorker , чтобы сделать это в другом потоке, чтобы ваш графический интерфейс не блокировался.

1 голос
/ 23 сентября 2011

Опубликовать код.Вы говорите, что Core является потоком, я предполагаю, что это означает class Core extends Thread, но нам нужно увидеть, где вы порождаете новый поток (вызов метода в классе, который расширяет поток, не заставляет его работать в отдельном потоке).нить).

Ваш рекурсивный (самопризывающийся) метод, если он никогда не прерывает рекурсию, будет слишком долго вызывать StackOverflowError.Если вы этого не получаете, то либо вы не используете рекурсивную функцию, либо где-то нарушаете рекурсию.Правильный способ закодировать метод, который никогда не завершается, это не рекурсия, это итерация.

Замораживание GUI почти наверняка, потому что в потоке GUI происходит некоторая трудоемкая обработкаЕще одна причина полагать, что метод в Core не выполняется в отдельном потоке.

0 голосов
/ 23 сентября 2011

Вам нужно проанализировать свой вызов самовыполняемого метода - это рекурсивный вызов - но каждый рекурсивный метод должен иметь какое-то условие, которое останавливает рекурсию - проверьте, при каких условиях в вашем случае вы должны получить такое условие

0 голосов
/ 23 сентября 2011

Я не понимаю, ПОЧЕМУ вы должны самостоятельно вызывать свой метод ...

Вы пытаетесь сделать какую-то рекурсию?

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

В зависимости от того, что вы пытаетесь использовать, вы можете использовать потоки Java или переосмыслить свой код.

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