-1

我有一个 FeatOrientation 类,在它的构造函数中的那个类中,我在一个单独的线程中执行两个操作,每个操作都在一个单独的线程中执行,并且我正在使用 CountDownLatch 以便当 gaussThread 完成时 laplaceThread 启动。

在具有主要方法的主类中,我正在使用 ExecutorService 和“.runAsync(new FeatOrientRun(bgrMat), featOrientExe);”

在运行方法中,我调用“calcFeatOrient”函数,并在该函数中从 FeatOrientation 类实例化一个对象。和线

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

我用它来阻塞主线程,直到 FeatOrientation 类中的两个线程完成,然后我进行一些计算或显示一些数据,如

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

问题是,在运行时我从控制台收到下面显示的输出,尽管 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();

我在 main 方法中从 FeatOrientation 类实例化了一个对象,然后,让主线程休眠 7 秒,在 7 秒后,我调用了以下几行

    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);
    }

我收到了outout。

请让我知道我在 ExecutorService 上做错了什么,以及为什么我在下面发布的代码中遵循的方法不起作用,所以我等到 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();
    }

}
4

1 回答 1

1

您的集合不是线程安全的,因此虽然任务可能已经完成,但这并不意味着结果对另一个线程可见。

Future<List<X>>您可以使用线程安全集合,但我更喜欢通过并调用返回结果,list = future.get() 这将等待结果并确保它以线程安全的方式传递,无论您使用哪个集合。

我认为这只是一个例子。
仅当您有独立的任务(复数)要执行时,运行线程才有意义。启动一个线程并等待它的响应是没有意义的,您最好在当前线程中进行工作,因为它会更简单更快。

于 2015-05-08T10:07:45.333 回答