2013-09-02 3 views
0

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

Я удивлен своими результатами:

test 
test 
Othertest 
test 
Othertest 
test 
test 
test 

Результаты я ожидал были для нити, чтобы вернуться еще случайно они, кажется, возвращаются последовательно в том же порядке! Кто-нибудь знает, почему? Означает ли это, что они не работают одновременно? Как я могу заставить их работать одновременно?

Вот мой код:

public class ThreadTest { 
    public static void main(String args[]) throws InterruptedException 
    { 
     new Thread(new ThreadTest().test()).start(); 
     new Thread(new ThreadTest().test()).start(); 
     new Thread(new ThreadTest().otherTest()).start(); 
     new Thread(new ThreadTest().test()).start(); 
     new Thread(new ThreadTest().otherTest()).start(); 
     new Thread(new ThreadTest().test()).start(); 
     new Thread(new ThreadTest().test()).start(); 
     new Thread(new ThreadTest().test()).start(); 
    } 

    public Runnable test() throws InterruptedException{ 
     Thread.sleep((long) (Math.random()*1000)); 
     System.out.println("test"); 
     return null; 
    } 

    public Runnable otherTest() throws InterruptedException{ 
     Thread.sleep((long) (Math.random()*1000)); 
     System.out.println("Othertest"); 
     return null; 
    } 

} 
+0

Они на самом деле не работает ничего в тему. –

ответ

1

Я думаю, что вы, возможно, лучше удачи с этим:

public class ThreadTest { 
public static void main(String args[]) throws InterruptedException 
{ 
    new Thread(test).start(); 
    new Thread(test).start(); 
    new Thread(otherTest).start(); 
    new Thread(test).start(); 
    new Thread(otherTest).start(); 
    new Thread(test).start(); 
    new Thread(test).start(); 
    new Thread(test).start(); 
} 

public static Runnable test = new Runnable() { 
    @Override 
    public void run() { 
     try { 
      Thread.sleep((long) (Math.random()*1000)); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("test"); 
    } 
}; 

public static Runnable otherTest = new Runnable() { 
    @Override 
    public void run(){ 
     try { 
      Thread.sleep((long) (Math.random()*1000)); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("Othertest"); 
    } 
}; 

}

Идея заключается в том, чтобы передать экземпляр Runnable в качестве аргумента в Thread конструктора. Вы на самом деле этого не делаете, потому что test() и otherTest() оба возвращаются null. Вышеприведенный код показывает один из способов запуска потоков таким образом, который я предполагаю, что вы хотите. Разумеется, возможны другие подходы.

+0

'Runnable' не разрешено бросать' InterruptedException'. Вы действительно должны поймать эти исключения и прервать текущий поток, когда это произойдет. –

+0

спасибо, я просто собирался прокомментировать, поэтому я отредактировал его комментарий – kevinn2065

+0

@ ChrisJester-Young - К сожалению. Вы правы в этом. Я вижу, что kevinn205 пошел вперед и исправил это. –

1

Ваш Thread реализация НЕПРАВИЛЬНО.

Вы должны либо реализовать Runnable и реализовать run() метод или вы должны расширить Thread класс и переопределить run() метод.

Что происходит, так это то, что ваш метод test() или otherTest() вызывается так же, как и вызовы любого метода. И так как у вас нет никакого метода run(), ваш Thread.start() не будет просто запускать что-либо.

Попробуйте изменить способ, как показано ниже.

public Runnable test() { 
    return new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Thread.sleep((long) (Math.random() * 1000)); 
       System.out.println("test"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
} 


public Runnable otherTest() { 
    System.out.println("Othertest"); 
    return new Runnable() { 

     @Override 
     public void run() { 
      try { 
       Thread.sleep((long) (Math.random() * 1000)); 
        System.out.println("Othertest"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
} 
+0

Спасибо, вы имеете в виду «новая тема (новый ThreadTest(). Test()). Start();"? как это сделать? – kevinn2065

2

Thread конструктор принимает Runnable, на котором, в конечном счете Thread выполнить метод run(). Прямо сейчас вы не возвращаете объект Runnable. вы возвращаетесь null. Таким образом, выполнение, которое вы выполняете в своих методах test() и otherTest(), выполняется синхронно.

Все ваше исполнение происходит в одном потоке. Это

new Thread(new ThreadTest().test()).start(); 

test() выполняет, спит на секунду, печатает "test" и возвращает null. Звонок start() ничего не делает, потому что Runnable - null. Это продолжается для каждого другого вызова.

Вам необходимо поместить все в свои методы test() и otherTest() внутри метода Runnable#run(). Например

new Thread(new Runnable() { 
    public void run() { 
     Thread.sleep((long) (Math.random()*1000)); 
     System.out.println("test"); 
    } 
}).start(); 

Рассмотрим исходный код run() метода Thread класса, который выполняется, когда start() называется

@Override 
public void run() { 
    if (target != null) { 
     target.run(); 
    } 
} 

Где target является Runnable ссылки вы передаете в конструктор. Очевидно, что если он null, он ничего не сделает.

+0

Спасибо, что определенно дает хорошее объяснение тому, что происходило – kevinn2065

1

Вам необходимо реализовать свои методы test и otherTest как реализации Runnable. Как так:

private static class Test implements Runnable { 
    @Override 
    public void run() { 
     try { 
      Thread.sleep((long) (Math.random()*1000)); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      return; 
     } 
     System.out.println("test"); 
    } 
} 

private static class OtherTest implements Runnable { 
    @Override 
    public void run() { 
     try { 
      Thread.sleep((long) (Math.random()*1000)); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      return; 
     } 
     System.out.println("Othertest"); 
    } 
} 

public static void main(String args[]) { 
    new Thread(new Test()).start(); 
    new Thread(new Test()).start(); 
    new Thread(new OtherTest()).start(); 
    new Thread(new Test()).start(); 
    new Thread(new OtherTest()).start(); 
    new Thread(new Test()).start(); 
    new Thread(new Test()).start(); 
    new Thread(new Test()).start(); 
} 

Можно, конечно, попытаться уменьшить дублирование немного:

private enum Runnables implements Runnable { 
    TEST { 
     @Override 
     public void run() { 
      if (!sleep()) return; 
      System.out.println("test"); 
     } 
    }, 
    OTHER_TEST { 
     @Override 
     public void run() { 
      if (!sleep()) return; 
      System.out.println("Othertest"); 
     } 
    }; 

    static boolean sleep() { 
     try { 
      Thread.sleep((long) (Math.random()*1000)); 
      return true; 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      return false; 
     } 
    } 
} 

public static void main(String args[]) { 
    new Thread(Runnables.TEST).start(); 
    new Thread(Runnables.TEST).start(); 
    new Thread(Runnables.OTHER_TEST).start(); 
    new Thread(Runnables.TEST).start(); 
    new Thread(Runnables.OTHER_TEST).start(); 
    new Thread(Runnables.TEST).start(); 
    new Thread(Runnables.TEST).start(); 
    new Thread(Runnables.TEST).start(); 
} 
+0

Спасибо за подробный ответ. Интересно, что вы можете обернуть несколько runnables в enum runnables, и поскольку вы вызываете их с помощью инструментов, они делают тогда runnable, когда вы обращаетесь к ним с помощью Runnables.test – kevinn2065

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