The scene of students choosing courses is similar to that of buying train tickets. Baidu summed up four ways
1. Thread lock. With synchronized, the performance drops sharply. java itself is multithreaded. It's not a wise choice to use it as a single thread. At the same time, if you add synchronized to distributed deployment, you cannot control concurrency.
2. Database lock. Optimistic lock, pessimistic lock. Based on the database optimistic lock face scenario, the concurrency is low and the user activity is low, It mainly focuses on the read-write ability of the Database disk. The concurrent ability is 300-700. With the improvement of the hard disk speed, it may be improved.
3. Cache (asynchronous write based on memory database) redis or memcached
Based on Redis
import java.util.List; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; public class MyRunnable implements Runnable { String watchkeys = "total"; //Monitoring keys int total; //Total items Jedis redis = new Jedis("127.0.0.1"); String userinfo; public MyRunnable() { } public MyRunnable(String userinfo, int count) { this.userinfo = userinfo; this.total = count; } public static void main(String[] args) { int total = 50; final Jedis redis = new Jedis("127.0.0.1"); redis.set("total", String.valueOf(total)); //Set the total number of items //redis.del("setsucc", "setfail"); redis.close(); //Create users, set the total number of items, and then start to rush ExecutorService executor = Executors.newFixedThreadPool(20); //Maximum concurrency (⊙ o ⊙) for (int i = 0; i < 1000; i++) { //Number of people to be snapped up executor.execute(new MyRunnable("user" + getRandomString(6), total)); } executor.shutdown(); } @Override public void run() { redis.watch(watchkeys); int num = Integer.valueOf(redis.get(watchkeys)); if (num >= 1 && num <= total) { Transaction tx = redis.multi(); //Open transaction tx.incrBy(watchkeys, -1); //Increment to - 1 List list = tx.exec(); //Commit the transaction and return null if the watchkeys are changed at this time if (list == null || list.size() == 0) { String failUser = "fail" + userinfo; String failInfo = "User:" + failUser + "Failed to rush"; System.out.println(failUser); redis.setnx(failUser, failInfo); //Business logic of failed flash purchase } else { for (Object obj : list) { String succUser = "succ" + obj.toString() + userinfo; String succInfo = "User:" + succUser + "The number of people who have been snapped up is now successful" + (1 - (num - total)); System.out.println(succInfo); redis.setnx(succUser, succInfo); //Business logic of successful flash purchase } } } else { String failUser = "kcfail" + userinfo; String failInfo = "User:" + failUser + "Product rush failed"; System.out.println(failUser); redis.setnx(failUser, failInfo); //Business logic of failed flash purchase return; } redis.close(); } private static String getRandomString(int length) { String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } }