Abstract: THE SERVER provided under the JUC package JDK1.5 is used for information exchange between two threads.
This article is shared from huawei cloud community “A Line of Java code to achieve two players to exchange equipment [Concurrent programming]”, by JavaLib Chen PI.
1, Sano1100What is it
The NON-recovery class provided under the JUC package in JDK 1.5 is used to exchange information between two threads. The San_recovery object is a container containing two cells, and the san_recovery method is used to fill the cell. When both cells are filled, the information in the two cells is automatically exchanged and returned to the calling thread, which uses the san_recovery tool to exchange information between the two threads.
The functionality may seem simple, but it can be useful in some situations, such as a game where two players trade equipment; Dating apps match men and women.
The following is a simple simulation of two players exchanging equipment.
package com.chenpi; import java.util.concurrent.Exchanger; /** * @description * @author * @date 2021/7/11 * @version 1.0 */ public class ChenPiMain {public static void main(String[] args) throws InterruptedException { Exchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (san_recovery); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "zhou Zhiru ").start(); new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (' san_recovery '); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "zhang Wuji ").start(); }} // the output results are as follows: trading success, Zhang Wuji dragon dao trading success, Zhou Zhiru obtained tianjianCopy the code
2, recovery
The Exchager class is used for information exchange between two threads. If one thread calls the Exchange method of the Non-recovery object, it blocks until the other thread exchanges information with it. The exchange information is returned to the calling thread for information exchange.
Exchager also uses spin and CAS mechanisms at the bottom.
Note that if more than two threads invoke the same Exchange method, the result is not expected. As long as two threads meet the condition, the match is considered successful and information is exchanged. The remaining threads that can’t be paired will block and wait until another thread can match it.
package com.chenpi; import java.util.concurrent.Exchanger; /** * @description * @author * @date 2021/7/11 * @version 1.0 */ public class ChenPiMain {public static void main(String[] args) { Exchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (san_recovery); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "zhou Zhiru ").start(); new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (' san_recovery '); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "zhang Wuji ").start(); new Thread(() -> { String str = null; Try {STR = sanotaiwan. exchange("); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "c ").start(); }} // the output results are as follows: trading success, Zhou Zhiru obtained false trading success of the heavenly Sword, Cheng Kun obtained dragon knifeCopy the code
Of course, the thread waiting for the exchange of information can be interrupted, for example, while the player is waiting for a transaction and suddenly the player is offline, it should be interrupted.
package com.chenpi; import java.lang.Thread.State; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Exchanger; /** * @description * @author * @date 2021/7/11 * @version 1.0 */ public class ChenPiMain {public static void main(String[] args) throws InterruptedException { Exchanger<String> exchanger = new Exchanger<>(); List<Thread> threads = new ArrayList<>(3); Thread thread1 = new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (san_recovery); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "Zhou Zhiruo "); threads.add(thread1); Thread thread2 = new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (' san_recovery '); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "Zhang Wuji "); threads.add(thread2); Thread thread3 = new Thread(() -> { String str = null; Try {STR = san_recovery. Exchange (' san_recovery '); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" transaction successful, "+ thread.currentThread ().getName() +" get "+ STR); }, "chengkun "); threads.add(thread3); for (Thread thread : threads) { thread.start(); } // Wait 5 seconds for thread.sleep (5000); for (Thread thread : threads) { System.out.println(thread.getName() + ":" + thread.getState()); If (thread.getState() == state.waiting) {thread.interrupt(); }}}} // resultsterminated :TERMINATED :WAITING :TERMINATED :TERMINATED :WAITING :TERMINATED :TERMINATED :WAITING ChengKun get null Java. Lang. InterruptedException at Java. Util. Concurrent. Exchanger. Exchange the at (Exchanger. Java: 568) com.chenpi.ChenPiMain.lambda$main$2(ChenPiMain.java:47) at java.lang.Thread.run(Thread.java:748)Copy the code
This demonstrates that a thread will wait forever if it cannot wait for another thread to exchange information with it. Actually, the RECOVERY server can also set the waiting time. For example, the system sets the matching time for the player to exchange equipment to 60 seconds, and if the time is exceeded, the transaction is terminated.
package com.chenpi; import java.util.concurrent.Exchanger; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * @description * @author * @date 2021/7/11 * @version 1.0 */ public class ChenPiMain {public static void main(String[] args) { Exchanger<String> exchanger = new Exchanger<>(); New Thread(() -> {try {// The timeout time is set to 5. String STR = sanoty.exchange (" sanoty.exchange ", 5, timeunit.seconds); System.out.println(" transaction succeeded, "+ thread.currentThread ().getName() +" get "+ STR); } catch (TimeoutException e) {system.out.println (" Transaction timeout!" ); e.printStackTrace(); } catch (InterruptedException e) {system.out.println (InterruptedException e); e.printStackTrace(); }}, "zhou Zhizao ").start(); }} // Transaction timeout! java.util.concurrent.TimeoutException at java.util.concurrent.Exchanger.exchange(Exchanger.java:626) at com.chenpi.ChenPiMain.lambda$main$0(ChenPiMain.java:22) at java.lang.Thread.run(Thread.java:748)Copy the code
3, Recovery application
Exchager is useful in applications such as genetic algorithms and pipe design. For example, two threads swap buffers, and the thread filling the buffer gets a freshly emptied buffer from the other thread when it needs it, and passes the filled buffer to the thread clearing the buffer.
package com.chenpi; import java.awt.image.DataBuffer; import java.util.concurrent.Exchanger; /** * @description * @author * @date 2021/7/11 * @version 1.0 */ public class ChenPiMain {recovery <DataBuffer> exchanger = new Exchanger<DataBuffer>(); DataBuffer initialEmptyBuffer = ... a made-up type DataBuffer initialFullBuffer = ... class FillingLoop implements Runnable { public void run() { DataBuffer currentBuffer = initialEmptyBuffer; try { while (currentBuffer ! = null) { addToBuffer(currentBuffer); if (currentBuffer.isFull()) { currentBuffer = exchanger.exchange(currentBuffer); } } } catch (InterruptedException ex) { ... handle ... } } } class EmptyingLoop implements Runnable { public void run() { DataBuffer currentBuffer = initialFullBuffer; try { while (currentBuffer ! = null) { takeFromBuffer(currentBuffer); if (currentBuffer.isEmpty()) { currentBuffer = exchanger.exchange(currentBuffer); } } } catch (InterruptedException ex) { ... handle ... } } } void start() { new Thread(new FillingLoop()).start(); new Thread(new EmptyingLoop()).start(); }}Copy the code
Click to follow, the first time to learn about Huawei cloud fresh technology ~