Java uses Exchanger to realize in game exchange equipment
- 2021-11-13 07:31:55
- OfStack
1 What is Exchanger
JDK 1.5
Start the provided under the JUC package
Exchanger
Class can be used to exchange information between two threads.
Exchanger
Object can be understood as a container containing two grids. By calling exchanger method, the grids are filled with information. When both grids are filled with information, the information in the two grids is automatically exchanged, and then the exchanged information is returned to the calling thread, thus realizing the information exchange between the two threads.
The function seems simple, but it is very useful in some scenarios, such as exchanging equipment between two players in the game; Dating software matches male and female favorite objects.
The following is a simple simulation of the next two players exchanging equipment.
package com.chenpi;
import java.util.concurrent.Exchanger;
/**
* @Description
* @Author Pericarpium tangerinae
* @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 = exchanger.exchange(" Dragon Slayer ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhou Zhiruo ").start();
new Thread(() -> {
String str = null;
try {
str = exchanger.exchange(" Heaven-leaning Sword ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhang Wuji ").start();
}
}
The output is as follows:
The transaction was successful and Zhang Wuji won Tu Longdao
The transaction was successful, and Zhou Zhiruo won the sword of relying on heaven
2 Exchanger Detailed Explanation
Exchager
Class can be used to exchange information between two threads. If one thread calls the exchange method of the Exchanger object, it will block until the other thread exchanges information with it, and the exchanged information will be returned to the calling thread, thus realizing the information exchange between the two threads.
Exchager
The bottom layer also uses spin and
cas
Mechanism.
Note: If more than two threads call the same 1
Exchanger
Object
exchange
Method, the result is unpredictable. As long as two threads meet the conditions, the match is considered successful and information is exchanged. The remaining threads that fail to be paired will be blocked for 1 until another thread can match and pair with it.
package com.chenpi;
import java.util.concurrent.Exchanger;
/**
* @Description
* @Author Pericarpium tangerinae
* @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 = exchanger.exchange(" Dragon Slayer ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhou Zhiruo ").start();
new Thread(() -> {
String str = null;
try {
str = exchanger.exchange(" Heaven-leaning Sword ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhang Wuji ").start();
new Thread(() -> {
String str = null;
try {
str = exchanger.exchange(" Fake Heaven-leaning Sword ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Cheng Kun ").start();
}
}
// The output is as follows
The transaction was successful, and Zhou Zhiruo got a fake sword of relying on heaven
The transaction was successful and Cheng Kun won the Tu Longdao
Of course, the thread waiting to exchange information can be interrupted. For example, when the player suddenly goes offline while waiting for the transaction, the thread 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 Pericarpium tangerinae
* @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 = exchanger.exchange(" Dragon Slayer ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhou Zhiruo ");
threads.add(thread1);
Thread thread2 = new Thread(() -> {
String str = null;
try {
str = exchanger.exchange(" Heaven-leaning Sword ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Zhang Wuji ");
threads.add(thread2);
Thread thread3 = new Thread(() -> {
String str = null;
try {
str = exchanger.exchange(" Fake Dragon Slayer ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
}, " Cheng Kun ");
threads.add(thread3);
for (Thread thread : threads) {
thread.start();
}
// Wait 5 Seconds
Thread.sleep(5000);
for (Thread thread : threads) {
System.out.println(thread.getName() + ":" + thread.getState());
// Break the thread if it is still blocking and waiting
if (thread.getState() == State.WAITING) {
thread.interrupt();
}
}
}
}
// The output is as follows
The transaction was successful and Zhang Wuji won Tu Longdao
The transaction was successful, and Zhou Zhiruo won the sword of relying on heaven
Zhou Zhiruo :TERMINATED
Zhang Wuji :TERMINATED
Cheng Kun :WAITING
The transaction was successful and Cheng Kun won null
java.lang.InterruptedException
at java.util.concurrent.Exchanger.exchange(Exchanger.java:568)
at com.chenpi.ChenPiMain.lambda$main$2(ChenPiMain.java:47)
at java.lang.Thread.run(Thread.java:748)
What is shown above is that if a thread can't wait for another thread to exchange information with it, it will wait for 1. Actually
Exchanger
You can also set to wait for a specified time. For example, the system sets the matching time for players to exchange equipment to 60 seconds, and if it exceeds the time, the transaction will be terminated.
package com.chenpi;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @Description
* @Author Pericarpium tangerinae
* @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 is set to 5 Seconds
String str = exchanger.exchange(" Dragon Slayer ", 5, TimeUnit.SECONDS);
System.out.println(" The transaction was successful, " + Thread.currentThread().getName() + " Obtain " + str);
} catch (TimeoutException e) {
System.out.println(" Trading timeout! ");
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(" Abnormal termination of transaction ");
e.printStackTrace();
}
}, " Zhou Zhiruo ").start();
}
}
// The output is as follows
Trading 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)
3 Exchanger application
Exchager
It is very useful in applications such as genetic algorithm and pipeline design. For example, when two threads exchange buffers, the thread that fills the buffer gets a newly emptied buffer from another thread when necessary, and passes the filled buffer to the thread that empties the buffer.
package com.chenpi;
import java.awt.image.DataBuffer;
import java.util.concurrent.Exchanger;
/**
* @Description
* @Author Pericarpium tangerinae
* @Date 2021/7/11
* @Version 1.0
*/
public class ChenPiMain {
Exchanger<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();
}
}