Java multithreading ~~~ Phaser class for task synchronization
In multi-threaded development, multiple tasks are often assigned to multiple threads, and each thread executes its tasks. However, each task is divided into several
Each stage is expected to be achieved by each thread at the same time. This means that every thread in each step must be synchronized. When a thread completes the first step, it must wait.
After other threads finish the first step, the next step can be continued. Consistent steps can solve many problems. The following is an example.
Check some files on the machine, find the files ending with logs, and set the last modification time to within 24 hours. We open three threads to complete this task.
Service. And use Phaser to synchronize tasks.
Package com. bird. concursey. charpet5; import java. io. file; import java. util. arrayList; import java. util. date; import java. util. list; import java. util. concurrent. phaser; import java. util. concurrent. timeUnit; /*** This class implements the operation of searching for files with a determined * extension modified in the last 24 hours in a folder and its subfolders *** @ author bird September 22, 2014 10:12:18 */ public class FileSearch implements Runnable {// store the folder in which the search operation will begin. private String initPath; // store the extension of the files we are going to look. private String end; // store the full path of the files we will find with the desired // characteristics. private List
Results; private Phaser phaser; public FileSearch (String initPath, String end, Phaser phaser) {this. initPath = initPath; this. end = end; this. phaser = phaser; this. results = new ArrayList
() ;}@ Overridepublic void run () {// The search won't begin until all the threads have been created. phaser. arriveAndAwaitAdvance (); System. out. printf ("% s: Starting. \ n ", Thread. currentThread (). getName (); File file = new File (initPath); if (file. isDirectory () {directoryProcess (file);} if (! CheckResults () {return;} filterResults (); if (! CheckResults () {return;} showInfo (); phaser. arriveAndDeregister (); System. out. printf ("% s: Work completed. \ n ", Thread. currentThread (). getName ();}/*** It records es a File object as a parameter and it processes all its files * and subfolders. ** @ param file */private void directoryProcess (File file) {File files [] = file. listFiles (); if (files! = Null) {for (int I = 0; I <files. length; I ++) {if (files [I]. isDirectory () {directoryProcess (files [I]);} else {fileProcess (files [I]) ;}}} /*** checks if its extension is equal to the one we are looking for ** @ param file */private void fileProcess (File file) {if (file. getName (). endsWith (end) {results. add (file. getAbsolutePath () ;}}/*** deleting the files that were modified more than 24 hours ago */private void filterResults () {List
NewResults = new ArrayList
(); Long actualDate = new Date (). getTime (); for (int I = 0; I <results. size (); I ++) {File file = new File (results. get (I); long fileDate = file. lastModified (); if (actualDate-fileDate <TimeUnit. MILLISECONDS. convert (1, TimeUnit. DAYS) {newResults. add (results. get (I) ;}} results = newResults;} private boolean checkResults () {if (results. isEmpty () {System. out. printf ("% s: Phase % d: 0 results. \ n ", Thread. currentThread (). getName (), phaser. getPhase (); System. out. printf ("% s: Phase % d: End. \ n ", Thread. currentThread (). getName (), phaser. getPhase (); // stop phaserphaser. arriveAndDeregister (); return false;} else {System. out. printf ("% s: Phase % d: % d results. \ n ", Thread. currentThread (). getName (), phaser. getPhase (), results. size (); // this thread has finished the actual // phase and it wants to be blocked until all the participants threads in the phased // operation finish the actual phase. phaser. arriveAndAwaitAdvance (); return true ;}} private void showInfo () {for (int I = 0; I <results. size (); I ++) {File file = new File (results. get (I); System. out. printf ("% s: % s \ n", Thread. currentThread (). getName (), file. getAbsolutePath ();} phaser. arriveAndAwaitAdvance ();} public static void main (String [] args) throws Exception {Phaser phaser = new Phaser (3); FileSearch system = new FileSearch ("C: \ Windows "," log ", phaser); FileSearch apps = new FileSearch (" C: \ Program Files "," log ", phaser ); fileSearch documents = new FileSearch ("C: \ ProgramData", "log", phaser); Thread systemThread = new Thread (system, "System "); thread appsThread = new Thread (apps, "appsThread"); Thread documentsThread = new Thread (documents, "documentsThread"); systemThread. start (); appsThread. start (); documentsThread. start (); systemThread. join (); appsThread. join (); documentsThread. join (); System. out. println ("Terminated:" + phaser. isTerminated ());}}
The program starts creating a Phaser object that will control the synchronization of the threads
At the end of each phase. The constructor of Phaser limits es the number of participants
A parameter. In our case, Phaser has three participant ipants. This number indicates to Phaser
The number of threads that have to execute an arriveAndAwaitAdvance () method before
Phaser changes the phase and wakes up the threads that were sleeping.
Once Phaser has been created, we launch three threads that execute three different
FileSearch objects.
The first instruction in the run () method of this FileSearch object is a call to
ArriveAndAwaitAdvance () method of the Phaser object. As we mentioned earlier,
Phaser knows the number of threads that we want to synchronize. When a thread callthis
Method, Phaser decreases the number of threads that have to finalize the actual phase and
Puts this thread to sleep until all the remaining threads finish this phase. Calling this method
At the beginning of the run () method makes none of the FileSearch threads begin their
Job until all the threads have been created.
At the end of phase one and phase two, we check if the phase has generated results and
List with the results has elements, or otherwise the phase hasn't generated results and the list
Is empty. In the first case, the checkResults () method callarriveandawaitadvance ()
As explained earlier. In the second case, if the list is empty, there's no point in the thread
Continuing with its execution, so it returns. But you have to your y the phaser that there will be
One less participant. For this, we used arriveAndDeregister (). This notifies the phaser
That this thread has finished the actual phase, but it won't particle in the future phases, so
The phaser won't have to wait for it to continue.
At the end of the phase three implemented in the showInfo () method, there is a call to
ArriveAndAwaitAdvance () method of the phaser. With this call, we guarantee that all
Threads finish at the same time. When this method ends its execution, there is a call to
ArriveAndDeregister () method of the phaser. With this call, we deregister the threads
Of the phaser as we explained before, so when all the threads finish, the phaser will have zero
Participant.
Finally, the main () method waits for the completion of the three threads and callthe
IsTerminated () method of the phaser. When a phaser has zero participant ipants, it enters
So called termination state and this method returns true. As we deregister all the threads
The phaser, it will be in the termination state and this call will print true to the console.