如何将CountDownLatch用于两个不同的线程,每个线程都具有相同的runnable类

时间:2020-12-12 20:56:02

How to use the CounDownLatch for two different threads each of them has the same runnable class?? i want FICS and fiCS_R7 to have the same runnable class FICS, but when fiCS_R3 finishes fiCS_R7 starts.

如何将CounDownLatch用于两个不同的线程,每个线程都有相同的runnable类?我希望FICS和fiCS_R7具有相同的可运行类FICS,但是当fiCS_R3完成时,fiCS_R7启动。

how can I do that.

我怎样才能做到这一点。

Code:

    public FICSFilter(Mat bgrMat, int csRadius) {
        // TODO Auto-generated constructor stub
        this.bgrMat = bgrMat;
        this.csRadius = csRadius;

        CountDownLatch latch = new CountDownLatch(1);

        this.fiCS_R3 = new Thread(new FICS(this.bgrMat, 3), "FICS_R" + this.csRadius);
        fiCS_R3.start();

        this.fiCS_R3 = new Thread(new FICS(this.bgrMat, 7), "FICS_R" + this.csRadius);
        fiCS_R7.start();

        //How to use the CounDownLatch for two different threads each of them has the same runnable class
        }

    private class FICS implements Runnable {

    private Mat bgrMat;
    private int csRadius;

    public FICS(Mat bgrMat, int csRadius) {
        // TODO Auto-generated constructor stub
        this.bgrMat = bgrMat;
        this.csRadius = csRadius;
    }

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

    public static void calcFICS(Mat bgrMat, int csRadius) {
    // TODO Auto-generated method stub

    ArrayList<Mat> onOffCSActRegMatsList = null;
    ArrayList<Mat> offOnCSActRegMatsList = null;

    ArrayList<Mat> onOffCSFullMatsList = null;
    ArrayList<Mat> offOnCSFullMatsList = null;

    onOffCSActRegMatsList = new ArrayList<Mat>();
    offOnCSActRegMatsList = new ArrayList<Mat>();

3 个解决方案

#1


Given two references r1 and r2 of type Runnable (note that r1 can also be equal to r2), it is very easy to run them sequentially, so that r1 happens-before r2:

给定两个类型为Runnable的引用r1和r2(注意r1也可以等于r2),顺序运行它们非常容易,因此r1发生在r2之前:

r1.run();
r2.run(); // will start when r1 has finished

This technique is called 'sequential execution' and allows you to reuse the thread that runs r1 (the current execution thread) for running r2 afterwards, without requiring any thread synchronization mechanisms like a CountDownLatch.

这种技术称为“顺序执行”,允许您重复运行r1(当前执行线程)的线程以后运行r2,而不需要任何线程同步机制,如CountDownLatch。

#2


You could perform the job with a CountDownLatch if for some reason you are obligated to do so. The trick is that the first thread must run without waiting on the latch, then decrement its counter, whereas the second must await the latch. There are any number of ways to implement the details, but here's one:

如果由于某种原因您有义务这样做,您可以使用CountDownLatch执行作业。诀窍是第一个线程必须在不等待锁存器的情况下运行,然后减少其计数器,而第二个线程必须等待锁存器。有许多方法可以实现细节,但这里有一个:

class FICSFilter {
    Mat bgrMat;
    int csRadius;

    public FICSFilter(Mat bgrMat, int csRadius) {
        this.bgrMat = bgrMat;
        this.csRadius = csRadius;
    }

    public void doFilter() {
        CountDownLatch openLatch = new CountDownLatch(0);
        CountDownLatch latch = new CountDownLatch(1);
        Thread fiCS_R3_Thread = new Thread(
                new FICS(3, openLatch, latch), "FICS_R3");
        Thread fiCS_R7_Thread = new Thread(
                new FICS(7, latch, latch), "FICS_R7");

        fiCS_R3.start();
        fiCS_R7.start();
        fics_R7.join();
    }

    private class FICS implements Runnable {

        private Mat bgrMat;
        private int csRadius;
        private CountDownLatch startLatch;
        private CountDownLatch signalLatch;

        public FICS(int csRadius, CountDownLatch startLatch,
                CountDownLatch signalLatch) {
            this.bgrMat = FICSFilter.this.bgrMat; // for clarity only
            this.csRadius = csRadius;
            this.startLatch = startLatch;         // assumed non-null
            this.signalLatch = signalLatch;       // assumed non-null
        }

        public void run() {
            startLatch.await();

            // ... perform the calculation ...

            signalLatch.countDown();
        }
    }
}

If you just need to run the jobs sequentially, however, and a CountDownLatch was simply one idea of how that might be accomplished, then this is a far superior solution:

但是,如果您只是需要按顺序运行作业,并且CountDownLatch只是一个如何实现这一点的想法,那么这是一个非常优越的解决方案:

class FICSFilter {
    Mat bgrMat;

    public FICSFilter(Mat bgrMat) {
        this.bgrMat = bgrMat;
    }

    public void doFilter() {
        Runnable fiCS_R3 = new FICS(this.bgrMat, 3);
        Runnable fiCS_R7 = new FICS(this.bgrMat, 7);

        fiCS_R3.run();
        fiCS_R7.run();
    }

    private class FICS implements Runnable {
        // As originally written ...
    }
}

The primary purpose of a CountDownLatch is to implement checkpointing, where one wants multiple threads to all reach the same point in their work before any of them proceed further. In that case, you initialize a latch with the number of threads, and at the checkpoint each one first decrements the latch and then waits on it:

CountDownLatch的主要目的是实现检查点,其中一个人希望多个线程在他们的任何进一步行进之前到达他们工作中的相同点。在这种情况下,您使用线程数初始化一个锁存器,并且在检查点,每个锁存器首先递减锁存器然后等待它:

latch.countDown();
latch.await();

The construct can be applied to other tasks, such as the one you asked about, but it is more natural for some than for others. It is quite unnatural for your particular task.

该构造可以应用于其他任务,例如您询问的任务,但对于某些人来说比其他任务更自然。你的特殊任务是非常不自然的。

#3


import java.util.ArrayList; import java.util.concurrent.CountDownLatch;

import java.util.ArrayList; import java.util.concurrent.CountDownLatch;

public class FICSFilter {

公共类FICSFilter {

Mat bgrMat;
int csRadius;


public FICSFilter(Mat bgrMat, int csRadius) {
    this.bgrMat = bgrMat;
    this.csRadius = csRadius;
    //How to use the CounDownLatch for two different threads each of them has the same runnable class
}

public static void main(String args[]){

    // CountDownLatch startLatch = new CountDownLatch(1);

    CountDownLatch doneLatch = new CountDownLatch(1);

    Mat lbgrmat = new Mat();

    Thread fiCS_R3 = new Thread(new FICS(lbgrmat, 10, doneLatch));
    Thread fiCS_R7 = new Thread(new FICS(lbgrmat, 20, null));

    fiCS_R3.start();

    try {
        System.out.println("\n Going into block state in main");
        doneLatch.await();
        System.out.println("\n Out of block state in main");

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    fiCS_R7.start();
}

}

class FICS implements Runnable {

class FICS实现Runnable {

CountDownLatch doneSignal;

Mat bgrMat;
int csRadius;

public FICS(Mat bgrMat, int csRadius, CountDownLatch llatch ) {
    this.bgrMat = bgrMat;
    this.csRadius = csRadius;
    this.doneSignal = llatch;
}

public void run() {
    calcFICS(this.bgrMat, this.csRadius);

}

public void calcFICS(Mat bgrMat, int csRadius)   {
    System.out.println("\n Radius : " + csRadius + " Thread : "+ Thread.currentThread().getName());
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    if (doneSignal != null )
        doneSignal.countDown();
}

}

The above code blocks on a latch in the main thread and only when the first thread FICS3 does its work and releases the latch, does the main thread start the next thread.

上面的代码阻塞主线程中的锁存器,并且只有当第一个线程FICS3完成其工作并释放锁存器时,主线程才会启动下一个线程。

#1


Given two references r1 and r2 of type Runnable (note that r1 can also be equal to r2), it is very easy to run them sequentially, so that r1 happens-before r2:

给定两个类型为Runnable的引用r1和r2(注意r1也可以等于r2),顺序运行它们非常容易,因此r1发生在r2之前:

r1.run();
r2.run(); // will start when r1 has finished

This technique is called 'sequential execution' and allows you to reuse the thread that runs r1 (the current execution thread) for running r2 afterwards, without requiring any thread synchronization mechanisms like a CountDownLatch.

这种技术称为“顺序执行”,允许您重复运行r1(当前执行线程)的线程以后运行r2,而不需要任何线程同步机制,如CountDownLatch。

#2


You could perform the job with a CountDownLatch if for some reason you are obligated to do so. The trick is that the first thread must run without waiting on the latch, then decrement its counter, whereas the second must await the latch. There are any number of ways to implement the details, but here's one:

如果由于某种原因您有义务这样做,您可以使用CountDownLatch执行作业。诀窍是第一个线程必须在不等待锁存器的情况下运行,然后减少其计数器,而第二个线程必须等待锁存器。有许多方法可以实现细节,但这里有一个:

class FICSFilter {
    Mat bgrMat;
    int csRadius;

    public FICSFilter(Mat bgrMat, int csRadius) {
        this.bgrMat = bgrMat;
        this.csRadius = csRadius;
    }

    public void doFilter() {
        CountDownLatch openLatch = new CountDownLatch(0);
        CountDownLatch latch = new CountDownLatch(1);
        Thread fiCS_R3_Thread = new Thread(
                new FICS(3, openLatch, latch), "FICS_R3");
        Thread fiCS_R7_Thread = new Thread(
                new FICS(7, latch, latch), "FICS_R7");

        fiCS_R3.start();
        fiCS_R7.start();
        fics_R7.join();
    }

    private class FICS implements Runnable {

        private Mat bgrMat;
        private int csRadius;
        private CountDownLatch startLatch;
        private CountDownLatch signalLatch;

        public FICS(int csRadius, CountDownLatch startLatch,
                CountDownLatch signalLatch) {
            this.bgrMat = FICSFilter.this.bgrMat; // for clarity only
            this.csRadius = csRadius;
            this.startLatch = startLatch;         // assumed non-null
            this.signalLatch = signalLatch;       // assumed non-null
        }

        public void run() {
            startLatch.await();

            // ... perform the calculation ...

            signalLatch.countDown();
        }
    }
}

If you just need to run the jobs sequentially, however, and a CountDownLatch was simply one idea of how that might be accomplished, then this is a far superior solution:

但是,如果您只是需要按顺序运行作业,并且CountDownLatch只是一个如何实现这一点的想法,那么这是一个非常优越的解决方案:

class FICSFilter {
    Mat bgrMat;

    public FICSFilter(Mat bgrMat) {
        this.bgrMat = bgrMat;
    }

    public void doFilter() {
        Runnable fiCS_R3 = new FICS(this.bgrMat, 3);
        Runnable fiCS_R7 = new FICS(this.bgrMat, 7);

        fiCS_R3.run();
        fiCS_R7.run();
    }

    private class FICS implements Runnable {
        // As originally written ...
    }
}

The primary purpose of a CountDownLatch is to implement checkpointing, where one wants multiple threads to all reach the same point in their work before any of them proceed further. In that case, you initialize a latch with the number of threads, and at the checkpoint each one first decrements the latch and then waits on it:

CountDownLatch的主要目的是实现检查点,其中一个人希望多个线程在他们的任何进一步行进之前到达他们工作中的相同点。在这种情况下,您使用线程数初始化一个锁存器,并且在检查点,每个锁存器首先递减锁存器然后等待它:

latch.countDown();
latch.await();

The construct can be applied to other tasks, such as the one you asked about, but it is more natural for some than for others. It is quite unnatural for your particular task.

该构造可以应用于其他任务,例如您询问的任务,但对于某些人来说比其他任务更自然。你的特殊任务是非常不自然的。

#3


import java.util.ArrayList; import java.util.concurrent.CountDownLatch;

import java.util.ArrayList; import java.util.concurrent.CountDownLatch;

public class FICSFilter {

公共类FICSFilter {

Mat bgrMat;
int csRadius;


public FICSFilter(Mat bgrMat, int csRadius) {
    this.bgrMat = bgrMat;
    this.csRadius = csRadius;
    //How to use the CounDownLatch for two different threads each of them has the same runnable class
}

public static void main(String args[]){

    // CountDownLatch startLatch = new CountDownLatch(1);

    CountDownLatch doneLatch = new CountDownLatch(1);

    Mat lbgrmat = new Mat();

    Thread fiCS_R3 = new Thread(new FICS(lbgrmat, 10, doneLatch));
    Thread fiCS_R7 = new Thread(new FICS(lbgrmat, 20, null));

    fiCS_R3.start();

    try {
        System.out.println("\n Going into block state in main");
        doneLatch.await();
        System.out.println("\n Out of block state in main");

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    fiCS_R7.start();
}

}

class FICS implements Runnable {

class FICS实现Runnable {

CountDownLatch doneSignal;

Mat bgrMat;
int csRadius;

public FICS(Mat bgrMat, int csRadius, CountDownLatch llatch ) {
    this.bgrMat = bgrMat;
    this.csRadius = csRadius;
    this.doneSignal = llatch;
}

public void run() {
    calcFICS(this.bgrMat, this.csRadius);

}

public void calcFICS(Mat bgrMat, int csRadius)   {
    System.out.println("\n Radius : " + csRadius + " Thread : "+ Thread.currentThread().getName());
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    if (doneSignal != null )
        doneSignal.countDown();
}

}

The above code blocks on a latch in the main thread and only when the first thread FICS3 does its work and releases the latch, does the main thread start the next thread.

上面的代码阻塞主线程中的锁存器,并且只有当第一个线程FICS3完成其工作并释放锁存器时,主线程才会启动下一个线程。