2013-05-08 2 views
0

Я получаю очень странное поведение при многопоточности. У меня есть два класса: DipoleTester и Dipole.Нечетное поведение с Runnable и ExecutorService

DipoleTester пытается создать несколько объектов Dipole, а затем запускать их асинхронно. Проблема в том, что DipoleTester просто запускает все свои объекты Dipole сразу, а не по 2 за раз.

Вот DipoleTester:

public class DipoleTester { 
    public static String DIR = "./save/"; 
    public static void main(String[] args) throws InterruptedException { 
     Dipole trial; 
     ExecutorService service = Executors.newFixedThreadPool(2);  

     for (int r = 10; r < 13; r += 1) { 
      double radius = (double) r/10000.0; 
      for (int matType = 0; matType < 3; matType++) { 
       String name = "Simple_mat"+matType + "_rad" + radius; 
       trial = new DipoleSimple(DIR + "Simple/", name); 
       trial.materialType = matType; 
       trial.RADIUS = radius; 
       service.submit(trial); 

      } 
     } 
     service.shutdown(); 
     service.awaitTermination(100, TimeUnit.HOURS); 
    } 
} 

И вот (соответствующие биты) от диполя

public abstract class Dipole implements Runnable{ 
    ...  
    public void run() { 
     initiate(); 
    } 
    public void initiate() { 
     DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); 
     Date date = new Date(); 
     System.out.println(dateFormat.format(date) + ": Starting: " + NAME); 
     model = ModelUtil.create(NAME); 
     model.modelNode().create("mod1"); 
     makeParams(); 
     makeVariables(); 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
    ... 
} 

Сейчас проблема заключается в том, что все потоки выполняются сразу, даже с Thread.sleep (5000)! Я понятия не имею, что происходит. Вот вывод на консоль:

05/08/2013 19:17:31: Starting: Simple_mat0_rad0.001 
05/08/2013 19:17:31: Starting: Simple_mat1_rad0.001 
05/08/2013 19:17:31: Starting: Simple_mat2_rad0.001 
05/08/2013 19:17:31: Starting: Simple_mat0_rad0.0011 
05/08/2013 19:17:31: Starting: Simple_mat1_rad0.0011 
05/08/2013 19:17:31: Starting: Simple_mat2_rad0.0011 
05/08/2013 19:17:31: Starting: Simple_mat0_rad0.0012 
05/08/2013 19:17:31: Starting: Simple_mat1_rad0.0012 
05/08/2013 19:17:31: Starting: Simple_mat2_rad0.0012 
+1

Значит, вы думали, что, поскольку в пуле потоков есть только 2 рабочих, эти двое сразу будут блокировать сна, а другие задачи придется ждать? Что ты здесь делаешь? Почему бы не использовать службу планирования, если вы хотите, чтобы они были распространены вовремя? – Rob

+0

Вы уверены, что даже добрались до «сна»? Я немного подрезал ваш код, чтобы его можно было скомпилировать, и он работал так, как вы ожидали, выполнив 2 задания, а затем спящий 5 секунд перед запуском еще двух задач. Но мне пришлось вытащить какой-то код, чтобы заставить его работать. Может быть, это исключение и никогда не доходит до сна? – cmbaxter

+0

Уважаемый @randomafk, 'sleep (5000)' следует поместить в класс 'DipoleTester' после каждого цикла. Вы не получите пользу от сна, пока он находится в классе Runnable. Если вы хотите начать' sleep' после каждого затем поместите 'sleep (5000)' после '' service.submit (trial) ''. Другое дело, почему вы не используете 'service.execute (trial)' вместо 'service.submit (trial)' –

ответ

1

Runnable Ваша задача бросать исключение, прежде чем он дойдет до Thread.sleep() вызова. Это позволяет начать выполнение следующей задачи. Все задачи не работают так быстро, что все они работают одновременно.

Сделайте ставку Thread.sleep() первым, что вы делаете в своем методе run(), и вы увидите, что за один раз запускаются только два потока.

Чтобы обнаружить такие сбои, вам необходимо указать examine экземпляр Future, который возникает в результате каждого звонка до submit(). Есть other methods for submitting a list of tasks оптом и ждут их завершения, что может быть лучше подходит для вашего приложения.

+0

Согласитесь с этим. Я попытался создать более простую версию кода OP только для тестирования, и он работает так, как он предполагал: http://pastebin.com/UQVuQ5ZL – gerrytan

+0

Согласен также с моим предыдущим комментарием :) – cmbaxter

+0

Большое спасибо! Я попытался использовать callable и invokeAll() вместо этого, и оказывается, что библиотека, которую я использую, бросает исключения повсюду ... Любая идея, почему она будет работать как singlethread, но не когда я пытаюсь запустить их одновременно? – randomafk