Simulated multi-threaded trigger
package com.ws.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.Lock; @Api (value = "lock mechanism", description = "Description locking mechanism" ) @RestController public class LockController { private static long count = 20;//黄牛 private CountDownLatch countDownLatch = new CountDownLatch(5); @Resource(name="redisLock") private Lock lock; @ApiOperation (value = "ticket" ) @RequestMapping(value = "/sale", method = RequestMethod.GET) public Long sale() throws InterruptedException { count = 20; countDownLatch = new CountDownLatch(5); System.out.println ( "------- total of 20 tickets, is divided into five windows on sale -------" ); new new PlusThread () Start ();. New new . PlusThread () Start (); new new PlusThread () Start ();. new new PlusThread () Start ();. new new PlusThread () Start ();. return COUNT; } // thread class simulated a train ticket window to buy a public class PlusThread the extends the Thread { Private int AMOUNT = 0; // grab how many tickets @Override public void run() { System.out.println (Thread.currentThread () getName (). + "Start booking" ); countDownLatch.countDown(); if (countDownLatch.getCount()==0){ System.out.println ( "Ticket result ------------------------------ ----------" ); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace (); } while (count > 0) { lock.lock(); the try { IF (COUNT> 0 ) { // analog ticket service processing AMOUNT ++ ; count--; } }finally{ lock.unlock(); } try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace (); } } System.out.println(Thread.currentThread().getName() + "售出"+ (amount) + "张票"); } } }
redis achieve lock
package com.ws.lock; import com.enjoy.utils.FileUtils; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import javax.annotation.Resource; import java.util.Arrays; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @Service public class RedisLock implements Lock { private static final String KEY = "LOCK_KEY"; @Resource private JedisConnectionFactory factory; private ThreadLocal<String> local = new ThreadLocal<>(); @Override // blocking the lock public void Lock () { // 1. Try locking IF (tryLock ()) { return ; } // 2. lock fails, the current task sleep for some time the try { Thread.sleep ( 10); // Properties waste } the catch (InterruptedException E) { e.printStackTrace (); } // 3. recursive calls, try to steal the lock again lock (); } @Override // blocking lock, using the command returns OK setNx of successful lock, and produce random value public Boolean tryLock () { // generate random values, identification number of this lock String UUID = UUID.randomUUID (). ToString () ; Jedis jedis = (Jedis) factory.getConnection().getNativeConnection(); /** * Key: When we use the key to lock * Uuid: a unique identification, the lock I added, belongs to me * NX: SET_IF_NOT_EXIST disposed in mode [] - only if the key does not exist, the value of this statement was provided into * PX: add validity to the key 1000 *: effective time of 1 second */ String ret = jedis.set(KEY, uuid,"NX","PX",1000); // set the value of success - grab the lock IF ( "the OK" .equals (RET)) { local.set (uuid); // grab the lock is successful, the lock identification number record into this thread Threadlocal --- return to true ; } // Key value inside there, I went into the uuid failed to set, grab the lock failure return false ; } // correct way to unlock public void UNLOCK () { // read lua script String Script = FileUtils.getScript ( "unlock.lua" ); // get the original connection redis Jedis jedis = (Jedis) factory.getConnection (). getNativeConnection (); // connection by performing the original redis lua script jedis.eval (script, Arrays.asList (KEY) , Arrays.asList (local.get ())); } //----------------------------------------------- @Override public Condition newCondition() { return null; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; } @Override public void lockInterruptibly() throws InterruptedException { } }
File Read Tools
package com.ws.utils; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class FileUtils { // no member variables --- stateless public static String getScript (String fileName) { String path = FileUtils.class.getClassLoader().getResource(fileName).getPath(); return readFileByLines(path); } public static String readFileByLines(String fileName) { FileInputStream file = null; BufferedReader reader = null; InputStreamReader inputFileReader = null; String content = ""; String tempString = null; try { file = new FileInputStream(fileName); inputFileReader = new InputStreamReader(file, "utf-8"); Reader = new new the BufferedReader (inputFileReader); // read into one line, until the end of the file is read into the null the while ((reader.readLine tempString = ()) =! null {) content + = tempString; } reader.close(); } catch (IOException e) { e.printStackTrace (); return null; } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } return content; } public static void main(String[] args) { String path = FileUtils.class.getClassLoader().getResource("unlock.lua").getPath(); String script = FileUtils.readFileByLines(path); System.out.println(script); } }
redis configuration class
package com.ws.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import redis.clients.jedis.JedisPoolConfig; @Configuration public class RedisConfig { @Bean public JedisPoolConfig jedisPoolConfig() { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMaxTotal(10000); return jedisPoolConfig; } @Bean public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) { JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName("192.168.42.111"); jedisConnectionFactory.setPort(6379); jedisConnectionFactory.setPassword("12345678"); jedisConnectionFactory.setUsePool(true); jedisConnectionFactory.setPoolConfig(jedisPoolConfig); return jedisConnectionFactory; } }
lua script
if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end