Dealing with automatic order number fetching for both outgoing and incoming orders in Java usually involves concurrency control in a multithreaded environment. To ensure the uniqueness and continuity of order numbers, we can use various strategies such as database self-incrementing IDs, distributed locking, or utilizing Java's concurrency utility classes likeAtomicLong
etc. Here, I will provide an example based on theAtomicLong
simple example for a stand-alone environment.
1. Scene Description
Suppose we have a simple inventory management system that needs to handle both outgoing and incoming operations, and each operation requires a unique order number. We will use theAtomicLong
to generate these order numbers because it provides thread-safe operation.
2. Solutions
(1)Define order number generator: UseAtomicLong
to ensure thread-safe generation of order numbers.
(2)Simulate outbound and inbound operations: Use threads to simulate concurrent operations, where each thread gets a unique order number from the order number generator when it executes.
3. Sample Code
import ;
public class OrderNumberGenerator {
private static final AtomicLong orderIdGenerator = new AtomicLong(1); // It is assumed that from the1commencement
// threaded task,Simulate outbound or inbound
static class OrderTask implements Runnable {
private final String type; // Outbound or Inbound
public OrderTask(String type) {
= type;
}
@Override
public void run() {
long orderId = (); // Thread-safe to get the next order number
(().getName() + " fulfillment " + type + " manipulate,order number:" + orderId);
}
}
public static void main(String[] args) {
// 创建并启动多个线程模拟并发manipulate
Thread t1 = new Thread(new OrderTask("ship out (goods)"), "ship out (goods)线程1");
Thread t2 = new Thread(new OrderTask("store"), "store线程1");
Thread t3 = new Thread(new OrderTask("ship out (goods)"), "ship out (goods)线程2");
Thread t4 = new Thread(new OrderTask("store"), "store线程2");
();
();
();
();
// Wait for all threads to complete
try {
();
();
();
();
} catch (InterruptedException e) {
();
}
}
}
4. Description
(1)AtomicLong
: this is the one that provides the atomic operationlong
Variable class for generating unique order numbers in a multi-threaded environment.
(2)threaded task:OrderTask
class implements theRunnable
interface for simulating outgoing or incoming operations. Each task receives an input from theorderIdGenerator
Get a unique order number in the
(3)main function: inmain
method, we created four threads to simulate concurrent operations and started them. Using thejoin()
method waits for all threads to complete to ensure that the main thread ends after outputting all order numbers.
5. Cautions
(1) If the system needs to handle order number generation in a distributed environment, it may be necessary to consider the use of database self-incrementing IDs, Redis atomic operations, or distributed ID generation algorithms (e.g., Snowflake algorithm Snowflake).
(2) In highly concurrent scenarios, theAtomicLong
performance may not be optimal, but it is efficient and easy enough to implement for simple stand-alone applications.
6. Complete Java code examples
This complete Java code example shows how to use theAtomicLong
to generate unique order numbers in a multi-threaded environment. This example simulates outbound and inbound operations in a simple inventory management system, each of which takes a unique order number from theAtomicLong
Get a unique order number in the
import ;
// Threaded task class used to simulate an outbound or inbound operation.
class OrderTask implements Runnable {
private final String type; // Outgoing or incoming order.
private final AtomicLong orderIdGenerator; // OrderIdGenerator; // The order number generator.
public OrderTask(String type, AtomicLong orderIdGenerator) {
= type; // OrderIdGenerator.
= orderIdGenerator.
}
@Override
public void run() {
// Get the next order number thread-safely.
long orderId = ();
// Simulate an outgoing or incoming operation (just print the information here)
(().getName() + " Performs " + type + " operation, order number: " + orderId);
}
}
public class OrderSystem {
// Order number generator, assuming it starts at 1.
private static final AtomicLong orderIdGenerator = new AtomicLong(1);
public static void main(String[] args) {
// Create and start multiple threads to simulate concurrent operations
Thread t1 = new Thread(new OrderTask("Outbound", orderIdGenerator), "Outbound Thread 1");
Thread t2 = new Thread(new OrderTask("Inbound", orderIdGenerator), "Inbound Thread 1");
Thread t3 = new Thread(new OrderTask("Outbound", orderIdGenerator), "Outbound Thread 2");
Thread t4 = new Thread(new OrderTask("Inbound", orderIdGenerator), "Inbound Thread 2");
// Start all threads
().
().
(); (); // Start all threads.
().
// Wait for all threads to complete (optional, depending on whether you need to wait for all operations to complete before continuing)
try {
().
().
(); ();
().
} catch (InterruptedException e) {
(); } catch (InterruptedException e) {
}
// If you don't need to wait for all threads to complete, you can omit the above join call
// ... Performing other operations
}
}
In this example, theOrderTask
class is a class that implements theRunnable
interface to a threaded task that accepts an operation type (outgoing or incoming) and aAtomicLong
instance as an order number generator. In therun
method, it first retrieves the data from theorderIdGenerator
to get a unique order number and then simulate the execution of an outgoing or incoming operation (here it simply prints a message).
OrderSystem
classmain
method creates four threads, each of which performs a differentOrderTask
instances. When these threads are started, they will concurrently perform outgoing or incoming operations from theorderIdGenerator
Get the unique order number in the
Note that due to the use of theAtomicLong
, so even in a multi-threaded environment, order number generation is thread-safe and requires no additional synchronization control.
In addition.main
method in thejoin
The call is optional and it is used to wait for all threads to complete. If our application can continue to perform other operations without waiting for these threads to complete after starting them, then we can omit thesejoin
calls. However, in this example, I kept them to show how to wait for all threads to complete.