CountDownLatch
concept
- Wait for the multithreading to complete. CountDownLatch allows one or more threads to wait for other threads to complete an operation.
- In java.util.cucurrent package, based on AQS implementation.
- This is done with a counter whose initial value is the number of threads. Each time a thread completes, the counter has a value of -1. When the counter has a value of 0, it indicates that all threads have completed, and the threads waiting on the lock can resume work.
For chestnuts
- To parse multiple sheets in an Excel, one sheet is processed by one thread, and the parsing is completed only after all the sheets are parsed.
CountDownLatch latch = new CountDownLatch(2); New Thread(() -> {system.out.println ("t1 start "); latch.countDown(); }, "t1").start(); New Thread(() -> {system.out.println ("t2 start "); latch.countDown(); }, "t2").start(); latch.await(); System. The out. Println (" end "); // out: T1 starts t2 startsCopy the code
A constructor
Public CountDownLatch(int count) {};Copy the code
methods
Public void await() throws InterruptedException {}; // The thread calling the await() method is suspended and waits until the count value is 0 before continuing. // Similar to await(), Public Boolean await(long timeout, TimeUnit Unit) throws InterruptedException {}; Public void countDown() {};Copy the code
CyclicBarrier Synchronization barrier
In real life, we often encounter such a situation that we need to wait for all the people before starting an activity. For example, when eating, we should wait for the whole family to be seated before we move chopsticks. When traveling, we should wait for the whole family to be seated before we start. When competing, we should wait for the athletes to take the field before we start.
Cyclicbarriers literally stand for “reusable barriers.” Cyclicbarriers are much simpler than countdownlatches. They are a combination of ReentrantLock and Condition.
A constructor
public CyclicBarrier(int parties) public CyclicBarrier(int parties, The second constructor takes a Runnable argument, which means the last task to reach the threadCopy the code
methods
public int await()
public int await(long timeout, TimeUnit unit)
Copy the code
chestnuts
The train starts when there are 20 people
CyclicBarrier barrier = new CyclicBarrier(20, () -> system.out.println (" CyclicBarrier ")); for(int i=0; i<100; i++) { new Thread(()->{ try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); }Copy the code
Phaser
Phase means phase. Phaser threads are executed in phases, and may be used if a program has several phases that require multiple threads.
The onAdvance method of Phaser rewriting defines four phases (this method is automatically called when the next phase is entered). The phase must start at 0. The two parameters phase of onAdvice are the number of phases, and registeredParties are the number of threads currently registered to participate. A final return value of false indicates that the process is not finished. Proceed to the next phase, and return true indicates that the process is finished. Simulated marriage:
static Random r = new Random(); static MarriagePhaser phaser = new MarriagePhaser(); static void milliSleep(int milli) { try { TimeUnit.MILLISECONDS.sleep(milli); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { phaser.bulkRegister(7); for(int i=0; i<5; i++) { new Thread(new Person("p" + i)).start(); } new Thread(new Person(" groom ")).start(); New Thread(new Person(" bride ")).start(); } static MarriagePhaser extends Phaser {@marriagePhaser protected Boolean onAdvance(int phase, Int registeredParties) {switch (phase) {case 0: system.out.println (" all parties present! + registeredParties); System.out.println(); return false; Case 1: system.out. println(" All finished! ") + registeredParties); System.out.println(); return false; Case 2: system.out. println(" Everyone left! ") + registeredParties); System.out.println(); return false; Case 3: system.out.println (" The wedding is over! Hugs for the bride and groom!" + registeredParties); return true; default: return true; } } } static class Person implements Runnable { String name; public Person(String name) { this.name = name; } public void arrive() { milliSleep(r.nextInt(1000)); System.out.printf("%s reaches the scene! \n", name); / / the current thread has reached the barrier, the waiting, the condition such as after meet to continue down a barrier to continue phaser. ArriveAndAwaitAdvance (); } public void eat() { milliSleep(r.nextInt(1000)); System. The out. Printf (" % s is finished! \n", name); phaser.arriveAndAwaitAdvance(); } public void leave() { milliSleep(r.nextInt(1000)); Leave System. Out. Printf (" % s! \n", name); phaser.arriveAndAwaitAdvance(); {if} private void hug () (name) equals (" groom ") | | name. Equals (" bride ")) {milliSleep (r.n extInt (1000)); Bridal chamber System. Out. Printf (" % s! \n", name); phaser.arriveAndAwaitAdvance(); } else {/ / the current thread exits, and the parties value minus 1 phaser. ArriveAndDeregister (); } } @Override public void run() { arrive(); eat(); leave(); hug(); }}Copy the code
Semaphore controls the number of concurrent threads
Semaphore is also a helper class for thread synchronization that maintains the number of threads currently accessing itself and provides a synchronization mechanism. Semaphore can be used to control the number of threads accessing resources at the same time, for example, to implement the number of concurrent accesses allowed for a file.
The main method
- Void acquire(): Acquires a license from this semaphore and blocks the thread until a license is provided, otherwise the thread is interrupted.
- Void release(): releases a license and returns it to the semaphore.
- Int availablePermits(): Returns the number of permits currently available in this semaphore.
- Boolean hasQueuedThreads(): Queries whether there are threads waiting to be fetched.
Semaphore s = new Semaphore(1, true); new Thread(()->{ try { s.acquire(); System.out.println("T1 running..." ); Thread.sleep(200); System.out.println("T1 running..." ); } catch (InterruptedException e) { e.printStackTrace(); } finally { s.release(); } }).start(); new Thread(()->{ try { s.acquire(); System.out.println("T2 running..." ); Thread.sleep(200); System.out.println("T2 running..." ); s.release(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); }Copy the code
Exchanger
Sano1100is an encapsulation tool provided in JDK 1.5 for data exchange between two worker threads. Simply put, when a thread wants to exchange data with another thread after completing a transaction, the first thread to retrieve data will wait for the second thread. The data is not exchanged until the second thread arrives with the data.
methods
Sanodomain Generic type, in which V indicates the data type that can be exchanged
- V exchange(V V) : Waits for another thread to reach this exchange point (unless the current thread is interrupted), then passes the given object to that thread and receives the object from that thread.
- V exchange(V V, long timeout, TimeUnit Unit) : Waits for another thread to reach this exchange point (unless the current thread is interrupted or the specified wait time is exceeded), then passes the given object to that thread and receives the object from that thread
chestnuts
static Exchanger<String> exchanger = new Exchanger<>();
new Thread(()->{
String s = "T1";
try {
s = exchanger.exchange(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + s);
}, "t1").start();
new Thread(()->{
String s = "T2";
try {
s = exchanger.exchange(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + s);
}, "t2").start();
Copy the code