How to synchronized one method when parallelStream call in Java?

386 Views Asked by At

I want to Synchronize functionB. I mean, when some Attriute object call functionA, there are always just run one of object's functionB in the same time. But functionC and functionD in each object can do it after functionB finished by themselves.

I tried to add synchronized in function B, but it seems like not work.

This is Attribute class:

public class Attribute {
    private String name;

    Attribute(String name) {
        this.name = name;
    }

    public void functionA() {
        synchronized (this) {
            functionB();
        }
        functionC();
        functionD();
    }

    private void functionB() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " " + i + " time functionB.");
        }
    }

    private void functionC() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " " + i + " time functionC.");
        }
    }

    private void functionD() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " " + i + " time functionD.");
        }
    }
    
    public static void main(String[] args) throws IOException {    
        ArrayList<Attribute> attributes = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
             attributes.add(new Attribute("No." + i));
        }
        attributes.parallelStream().forEach(Attribute::functionA);
    }
}

After execute above code, the console show:

No.3 0 time functionB.
No.4 0 time functionB.
No.2 0 time functionB.
No.2 1 time functionB.
No.2 2 time functionB.
No.1 0 time functionB.
No.1 1 time functionB.
...

But I expect it:

No.3 0 time functionB.
No.3 1 time functionB.
No.3 2 time functionB.
No.3 3 time functionB.
No.3 4 time functionB.
No.1 0 time functionB.
No.1 1 time functionB.
No.1 2 time functionB.
No.1 3 time functionB.
No.1 4 time functionB.
No.4 0 time functionB.
No.4 1 time functionB.
...
No.1 1 time functionD.
No.3 3 time functionC.
No.2 3 time functionD.
No.1 2 time functionD.
No.4 2 time functionC.
1

There are 1 best solutions below

4
On

Can you use ExecutorService like below.

ExecutorService executorService = Executors.newFixedThreadPool(10);

    public void functionA() {
        synchronized (this) {
            functionB();
        }
        executorService.submit(this::functionC);
        executorService.submit(this::functionD);
    }

Not exactly elegant, but it will interleave between C and D after B is completed.