You know Java, Phaser doing it?

1 Overview

In this article, we will see java.util.concurrent package Phaser  structure. It is very similar to the CountDownLatch, allow us to coordinate the implementation of the thread. Compared with CountDownLatch, it has some extra features.

Phaser is required before the thread continues to wait for a dynamic number of barriers. In CountDownLatch, the numbers can not be dynamically configured, you need to provide when you create the instance.

2. Phaser API

The Phaser enabled us to create obstacles before going to the next step in the logical thread to wait.

We can coordinate multiple execution phase, reuse Phaser instance for each program stage. Each stage can have a different number of threads waiting forward to another stage. We will look at an example of using a later stage.

To participate in the coordination, threads need to use Phaser instance register () itself. Please note: this will only increase the number of registered parties, we can not check whether the current thread has been registered - we have to realize subclass to support this operation.

Thread by calling arriAndAwaitAdvance () to prevent it from reaching the barrier, which is a blocking method. When the number reaches the amount equal to the registered program execution will continue, and the number will increase. We can get the current number by calling getPhase () method.

When a thread completes its work, we should call arrivalAndDeregister () method is expressed in this particular stage not consider the current thread.

3. Phaser API logic implemented

Suppose we want to coordinate multiple stages of action. Three threads will handle the first phase, two threads will handle the second phase.

We will create LongRunningAction class that implements Runnable interface:


class LongRunningAction implements Runnable {
    private String threadName;
    private Phaser ph;

    LongRunningAction(String threadName, Phaser ph) {
        this.threadName = threadName;
        this.ph = ph;
        ph.register();
    }

    @Override
    public void run() {
        ph.arriveAndAwaitAdvance();
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ph.arriveAndDeregister();
    }

}

When our operation class is instantiated, we use the register () method to register Phaser instance. This will increase the number of threads that use the Phaser particular.

Call to arrivalAndAwaitAdvance () will cause the current thread to wait on the barrier. As already mentioned, when the number reached to become registered with the same, the execution will continue.

After processing is complete, the current thread unregister by calling arrivalAndDeregister () method.

Let's create a test case, in which we will launch three LongRunningAction thread and blocking barrier. Next, after the operation is completed, we will create two more LongRunningAction threads that will perform the next stage of processing.

We will pass 1 when creating Phaser instance as a parameter from the main thread. This is equivalent to calling the register () method from the current thread. We do this because, when we create three worker threads, the main thread is a coordinator, so Phaser need to register four threads:


ExecutorService executorService = Executors.newCachedThreadPool();

Phaser ph = new Phaser(1);

assertEquals(0, ph.getPhase());

After the initialization phase is equal to zero.

The phase shifter class has a constructor, we can pass it on to the parent instance. We have a large number of participants will encounter a large case of synchronous contention costs, it is very useful. In this case, it is possible to establish Phasers instance, the sub-groups to share a common subset of the parent group.

Next, let us start operating three LongRunningAction thread, it will wait on the barrier, until we called from the main thread arrivalAndAwaitAdvance () method.

Remember, we've initialized with the Phaser 1, and multiple calls to the register () three times. Now, three action thread has announced that they have reached the barrier, so you need to call arriAndAwaitAdvance again () - one from the main thread:


executorService.submit(new LongRunningAction("thread-1", ph));

executorService.submit(new LongRunningAction("thread-2", ph));

executorService.submit(new LongRunningAction("thread-3", ph));

ph.arriveAndAwaitAdvance();

assertEquals(1, ph.getPhase());

After this stage is completed, getPhase () method returns a, as with the first step has completed processing.

Suppose that two threads should be the next stage of processing. We can use the Phaser achieve this, because it allows us to dynamically configure the number of threads should wait on the barrier. We are starting two new threads, but not until after the call arrivalAndAwaitAdvance () from the main thread will execute these threads (the same as in the previous case):

executorService.submit(new LongRunningAction("thread-4", ph));

executorService.submit(new LongRunningAction("thread-5", ph));

ph.arriveAndAwaitAdvance();

assertEquals(2, ph.getPhase());

ph.arriveAndDeregister();

After this, getPhase () method returns the number of phases equal to 2. When we want to complete our program, we need to call arriAndDeregister () method, because the main thread is still registered in the Phaser. When the number of registered political parties led to cancellation of zero phase shift is terminated. All calls to the synchronization method are no longer blocked, and will return immediately.

Running the program produces the following output (available with full source code statements in the code print line repository):


This is phase 0

This is phase 0

This is phase 0

Thread thread-2 before long running action

Thread thread-1 before long running action

Thread thread-3 before long running action

This is phase 1

This is phase 1

Thread thread-4 before long running action

Thread thread-5 before long running action

We see that all threads are waiting to perform until the barrier is opened. Only when the current implementation of a successful completion of the next phase of implementation.

4 Conclusion

We looked Phaser constructed from java.util.concurrent, and use the Phaser class implements the logical coordination of multiple stages.

image

Welcome to the number of public attention: " Java confidant " public concern number, reply " 1024 " you know, receive a free 30 classic programming books . I am concerned about the progress with 100,000 programmers. Java knowledge is updated daily Oh, look forward to your arrival!

image

Guess you like

Origin blog.csdn.net/feilang00/article/details/87974491