Java: поток не работает

1

Я пытаюсь запустить поток в for-loop. Эта задача должна ждать только второй (Thread.sleep()), поэтому каждый раз, когда цикл начинается снова, запускается новый поток, и он должен вызывать код после того, как поток будет ждать, пока он не будет выполнен.

public void count()
{
    for(int i = 29; i>=0; i--)
    {
        Thread t1;
        t1 = new Thread(new TimerClass());
        t1.start();
        String s = String.valueOf(i); 
        jLabel6.setText(s);
        System.out.println(s);
    }
}


public class TimerClass implements Runnable{

   @Override
   public void run()
   {
       try{
           Thread.sleep(1000);
           System.out.println("Timer");
       } catch(InterruptedException e)
       {
       }
   }
}

Как вы можете видеть, я реализовал оба метода System.out.println(), чтобы проверить, действительно ли они выполнены. Я получаю это:

29
28
27
26
...//25 - 3
2
1
0
Timer
Timer
Timer
//in all 29 times Timer

Так должно быть 29, Таймер, 28, Таймер и т.д., Но это не так. Кто-нибудь знает, что не так с кодом? Большое спасибо.

  • 0
    Исключение должно быть зарегистрировано. :)
  • 1
    процессор намного быстрее :)
Теги:
multithreading

8 ответов

6

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

Фактически, учитывая, что все ваши потоки спят целую секунду, и вы всего лишь зацикливаете 29 раз, вам гарантируется, что ваш цикл завершит (и распечатает все номера) до ваших потоков. Добавьте спать в основной цикл, если вы хотите, чтобы потоки были напечатаны - помните, основной цикл не останавливается при запуске потока.

  • 0
    где в коде это должно быть размещено?
  • 0
    Вы можете поставить его сразу после t1.start();
Показать ещё 3 комментария
3

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

public void count()
{
    for(int i = 29; i>=0; i--)
    {
        Thread t1;
        t1 = new Thread(new TimerClass());
        t1.start();
        t1.join();
        String s = String.valueOf(i); 
        jLabel6.setText(s);
        System.out.println(s);
    }
}

Вот мой код для нереста 2 нитей или один поток зависит от размера массива, но в моем случае эти потоки выполняют гораздо более сложные задачи, а затем ждут 1 секунду

for (int i = 0; i < array.size(); i += 2) {
            Thread t1 = null;
            Thread t2 = null;

            if (i < array.size() - 1 && array.size() > 1) {

                t1 = new Thread(array.get(i));
                t2 = new Thread(array.get(i + 1));
                t1.start();
                t2.start();

            }

            else {

                t2 = new Thread(array.get(i));

                t2.start();
            }
            if (t1 != null)
                t1.join();
            if (t2 != null)
                t2.join();
              }

В моем коде я заполняю arrayList объектами, реализующими интерфейс Runnable.

  • 0
    теперь работает, что число и таймер печатаются друг за другом, но реальным смыслом всего этого было обновление jLabel6. Теперь GUI появляется только после того, как я == 0. У вас есть идеи для этого?
  • 0
    Вы должны исследовать темы более глубоко. Измените свой класс TimerClass, чтобы он мог получить доступ к jLabel6. Теперь то, что происходит, поток выполняет свою задачу, тогда основным методом является установка текста для jlabel.
Показать ещё 2 комментария
2

Даже если вы спите нить за 1 мс, ваши результаты будут одинаковыми. Если вы можете управлять потоком спать в течение времени, меньшего, чем требуется для печати результатов, ваш результат может быть таким, как ожидалось. Вот мой код, где я набрал время 1 мс, но все же результаты одинаковы.

public class MultiThreading implements Runnable
{
       public void run()
       {
           try
           {
               Thread.sleep(1);
               System.out.println("Timer");
           } 
           catch(Exception e)
           {

           }
       }

    public static void main(String [] args)
    {
        for(int i = 29; i>=0; i--)
        {
            Thread t1;
            t1 = new Thread(new MultiThreading());
            t1.start();
            String s = String.valueOf(i); 
            System.out.println(s);
        }
     }
}

Если вы прокомментируете метод Thread.sleep(1), то ваши результаты будут такими, как вы ожидали.

0

Другая аналогия с нитями в рубашке:

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

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

Если вы хотите дать какую-то работу, а затем дождитесь ее завершения, используйте t1.join(), как это было предложено другими. Но если вы это делаете, бессмысленно создавать новые потоки, потому что вы не пытаетесь что-то обрабатывать параллельно (со многими коллегами), но в определенном порядке - вы можете просто это сделать сами.

0

Темы интересны. Подумайте о виртуальном потоке как о физическом потоке. На одежде есть много нитей, все одновременно работают, чтобы сжать рубашку. В виртуальных условиях, что Thread.start() делает это начать нить на другой нити ПОКА следующий код продолжает выполняться, (то есть две темы одновременно работать как 2 бегунов работать рядом друг с другом). Подумайте о поломке точки сразу после Thread.start(). Вы поймете.

Для желаемого эффекта просто поставьте Thread.sleep() в основной цикл. Это приведет к

29
Timer
28
Timer
// etc.

Надеюсь, это помогло.

Джарод.

0

Delay достаточно много, чтобы позволить циклу for в count() до завершения, прежде чем он может печатать "таймер" из потока.

0

То, что вы на самом деле хотите сделать, это заблокировать основной поток, пока работает другой поток. Пожалуйста, не используйте заявления типа сна #, так как они ненадежны, чтобы "сделать работу вашего приложения". Вместо этого вы хотите использовать Thread # join. См. Dharr его код для примера.

Кроме того, лучше использовать Executors и ExecutorServices при создании потоков или выполнении задач async.

  • 0
    Я уже выложил :)
0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню