-1

У меня есть класс FeatOrientation, и в этом классе в его конструкторе я выполняю две операции каждый в отдельном потоке, и я использую CountDownLatch, так что, когда gaussThread заканчивает запуск laplaceThread.ExecutorService не блокируется до тех пор, пока нить finishe

и в основном классе, который имеет основной метод, я использую ExecutorService и в «.runAsync (новый FeatOrientRun (bgrMat), featOrientExe);

В методе выполнения я называю функцию calcFeatOrient и в этой функции я создаю объект из класса FeatOrientation. и линия

"CompletableFuture.allOf(future0).join();" 

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

"Log.D(TAG, "MainClass", "SmoothedImgList:" + fo.getSmoothedImgList().size());". 

проблема, во время выполнения я получаю вывод, показанный ниже из консоли despit. getSmoothedImgList не пуст. Я знал, что он не пуст, закомментировав следующие три строки:

featOrientExe = Executors.newFixedThreadPool(1); 
    future0 = CompletableFuture.runAsync(new FeatOrientRun(bgrMat), featOrientExe); 

CompletableFuture.allOf(future0).join();//blocks the main thread till future0, and future1 finishes 

    featOrientExe.shutdown(); 

и я экземпляр объекта из класса FeatOrientation в основном методе, а затем сделал основной поток спать в течение 7 секунд и после 7 секунд, я назвал следующие строки:

и я получил выход.

Пожалуйста, дайте знать, что я делаю неправильно с ExecutorService, и почему подход, который я следую ниже, не работает desoite, я жду, пока класс FeatOrientation не закончит работу.

консоль из положить:

1: Error: FeatOrientation -> getSmoothedImgList: smoothedImgList is empty 
Exception in thread "main" java.lang.NullPointerException 
at com.example.featorientation_00.MainClass.main(MainClass.java:39) 

главный класс:

public static void main(String[] args) { 
    MatFactory matFactory = new MatFactory(); 
    FilePathUtils.addInputPath(path_Obj); 
    Mat bgrMat = matFactory.newMat(FilePathUtils.getInputFileFullPathList().get(0)); 

    featOrientExe = Executors.newFixedThreadPool(1); 
    future0 = CompletableFuture.runAsync(new FeatOrientRun(bgrMat), featOrientExe); 
    CompletableFuture.allOf(future0).join();//blocks the main thread till future0, and future1 finishes 
    featOrientExe.shutdown(); 

    Log.D(TAG, "MainClass", "SmoothedImgList:" + fo.getSmoothedImgList().size()); 
    Log.D(TAG, "MainClass", "SubSampledImgList:" + fo.getSubSampledImgList().size()); 

    for (int i = 0; i < fo.getSmoothedImgList().size(); i++) { 
     ImageUtils.showMat(fo.getSmoothedImgList().get(i), "SmoothedImgList_" + i); 
    } 
    for (int i = 0; i < fo.getSubSampledImgList().size(); i++) { 
     //Mat laplaceImg = SysUtils.applyLaplac(fo.getSubSampledImgList().get(i)); 
     //ImageUtils.showMat(laplaceImg, "getSubSampledImgList" + i); 
    } 


} 

static class FeatOrientRun implements Runnable { 

    private Mat bgrMat; 
    public FeatOrientRun(Mat bgrMat) { 
     // TODO Auto-generated constructor stub 
     this.bgrMat = bgrMat; 
    } 

    public void run() { 
     // TODO Auto-generated method stub 
     calcFeatOrient(this.bgrMat); 
    } 
} 

public static void calcFeatOrient(Mat bgrMat) { 
    // TODO Auto-generated method stub 
    fo = new FeatOrientation(bgrMat); 
} 

FeatOrientation класс:

public FeatOrientation(Mat bgrMat) { 
    // TODO Auto-generated constructor stub 
    this.origBGRImgList = new ArrayList<Mat>(); 
    this.origGSImgList = new ArrayList<Mat>(); 
    this.smoothedImgList = new ArrayList<Mat>(); 
    this.downSampledImgList = new ArrayList<Mat>(); 
    this.laplaceImgList = new ArrayList<Mat>(); 
    this.latch = new CountDownLatch(1); 

    if (bgrMat != null) { 
     if (!bgrMat.empty()) { 
      if (bgrMat.channels() == 3) { 
       if ((bgrMat.size().width >= SysConsts.MIN_IMG_WIDTH) && (bgrMat.size().height >= SysConsts.MIN_IMG_HEIGHT)) { 

        this.bgrMat = bgrMat; 

        this.gaussThread = new Thread(new GaussRun(this.bgrMat, this.latch), "GAUSSIAN_THREAD"); 
        this.laplaceThread = new Thread(new LaplaceRun(this.latch), "GAUSSIAN_THREAD"); 
        this.gaussThread.start(); 
        this.laplaceThread.start(); 

       } else { 
        Log.E(TAG, "FeatOrientation", "the Mat you passed to the constructor has size: " + this.bgrMat.size() + 
          " the minimum width must = " + SysConsts.MIN_IMG_WIDTH + 
          " and the maximum height must = " + SysConsts.MIN_IMG_HEIGHT); 
       } 
      } else { 
       Log.E(TAG, "FeatOrientation", "BGR mat passed to the constructor does not has 3 channels."); 
      } 
     } else { 
      Log.E(TAG, "FeatOrientation", "BGR mat passed to the constructor is empty"); 
     } 
    } else { 
     Log.E(TAG, "FeatOrientation", "the BGR mat you passed to the constructor is null"); 
    } 
} 

class GaussRun implements Runnable { 

    private Mat bgrMat; 
    private CountDownLatch latch; 

    public GaussRun(Mat bgrMat, CountDownLatch latch) { 
     // TODO Auto-generated constructor stub 
     this.bgrMat = bgrMat; 
     this.latch = latch; 
    } 

    public void run() { 
     // TODO Auto-generated method stub 
     applyGaussianPyr(this.bgrMat); 
     this.latch.countDown(); 
    } 

} 

class LaplaceRun implements Runnable { 

    private CountDownLatch latch; 

    public LaplaceRun(CountDownLatch latch) { 
     // TODO Auto-generated constructor stub 
     this.latch = latch; 
    } 
    public void run() { 
     // TODO Auto-generated method stub 
     try { 
      this.latch.await(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     applyLaplacianPyr(); 
    } 

} 

ответ

1

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

Вы можете использовать потокобезопасную коллекцию, но я предпочитаю возвращать результаты через Future<List<X>> и звонить по телефону list = future.get(). Это будет ждать результата и гарантировать, что оно передается в потоковом безопасном режиме, независимо от того, какую коллекцию вы используете.

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

+0

спасибо за ваш ответ. фактически я не ожидаю результатов от CompletableFuture.runAsync (новый FeatOrientRun (bgrMat), featOrientExe); , я просто хочу подождать, пока он закончится, так что я могу делать некоторые операции – user2121

+0

@ user2121, если вы понимаете, что даже когда задача завершается, это не значит, что вы можете использовать результаты этой задачи в другом потоке, если только вы считаете безопасность потока. –

+0

@ user2121, точка зрения Питера заключается в том, что в то время вы выполняете только одну задачу, поэтому почему бы не сделать все это в одном потоке, вместо того, чтобы размножать несколько потоков для выполнения задач один за другим. – Kishore