redis lock operation

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) + "张票");
        }
    }
}
View Code

 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 {
    }

}
View Code

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);
    }
}
View Code

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;
    }
}
View Code

 lua script

if redis.call("get",KEYS[1]) == ARGV[1] then 
    return redis.call("del",KEYS[1]) 
else 
    return 0 
end
View Code

 

Guess you like

Origin www.cnblogs.com/Soy-technology/p/11817370.html