多執行緒模擬高併發情況redis 與資料庫快取不一致
import com.mysql.jdbc.Connection; import entity.User; import org.junit.Test; import redis.clients.jedis.Jedis; import java.sql.*; import java.util.LinkedList; /** * @描述 佇列解決高併發,redis,快取與資料庫不一致問題 * @引數 $ * @返回值 $ * @建立人 [email protected] * @建立時間 $ * @修改人和其它資訊 */ public class TestQueueSolution { //獲得mysqlconnection public Connection getMysqlConn() { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/redistest?useSSL=false"; String username = "root"; String password = "root"; Connection conn = null; try { Class.forName(driver); //classLoader,載入對應驅動 conn = (Connection) DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; } public User execQuerySql(Connection connection,String sqlStr, LinkedList parms) throws SQLException { PreparedStatement pstmt = null; ResultSet resultSet = null; pstmt = connection.prepareStatement(sqlStr); for (int i = 1 ; i <= parms.size() ; i++ ){ ///記得 後面跟的是 i-1 pstmt.setObject(i,parms.get(i-1)); } resultSet = pstmt.executeQuery(); User user = null; while (resultSet.next()){ user = new User(); System.out.println("----------------"); user.setId(resultSet.getInt("id")); user.setAge(resultSet.getInt("age")); user.setBirthday(resultSet.getDate("birthday")); user.setName(resultSet.getString("name")); } return user; } //執行sql 以及引數 public Integer exeuUpdateTheSqlWithParms(Connection connection,String sql,LinkedList parms) throws SQLException { PreparedStatement pstmt = null; ResultSet resultSet = null; pstmt = connection.prepareStatement(sql); //設定引數 for (int i = 1 ; i <= parms.size(); i++){ pstmt.setObject(i,parms.get(i-1)); } Integer count = pstmt.executeUpdate(); return count; } //刪除redis並延遲更新資料的執行緒 class UpdateRedisDataBaseThread implements Runnable{ public String redisKey; //每個執行緒獲取自己的connection public Connection connection; //資料庫 名字 public String parmName; //設定資料年齡 public Integer age; public UpdateRedisDataBaseThread(String redisKey, String parmName, Integer age) { this.redisKey = redisKey; this.parmName = parmName; this.age = age; } @Override public void run() { //每個執行緒自己 的 redis 客戶端 Jedis jedis = new Jedis("127.0.0.1",6379); //如果存在則進行刪除 if ( jedis.exists(this.redisKey) ){ System.out.println("del a value from redis :" + this.redisKey); jedis.del(this.redisKey); } //模擬延遲更新資料庫 //設定引數 this.connection = getMysqlConn(); String sqlStr = "update t_user set age = ? where name = ?"; LinkedList parm_link = new LinkedList(); parm_link.add(age); parm_link.add(parmName); try { //休眠一秒 System.out.println("UpdateRedisDataBaseThread sleep 3s"); Thread.sleep(3000); Integer count = exeuUpdateTheSqlWithParms(connection,sqlStr,parm_link); System.out.println("UpdateRedisDataBaseThread update database count:"+count); } catch (SQLException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } //直接更改資料庫的執行緒 class SelectThread implements Runnable{ //每個執行緒獲取自己的connection public Connection connection; //查詢引數 public String parmName; //查詢結果 public String queryResult; public SelectThread(String parmName) { this.parmName = parmName; } @Override public void run() { //每個執行緒自己 的 redis 客戶端 Jedis jedis = new Jedis("127.0.0.1",6379); //如果redis存在則直接得到值 if (jedis.exists(parmName)){ System.out.println("SelectThread can not get value parm:" + this.parmName); this.queryResult = jedis.get(parmName); }else { //快取沒有則到資料庫查詢 this.connection = getMysqlConn(); String sqlStr = "select * from t_user where name = ?"; LinkedList parm_link = new LinkedList(); parm_link.add(parmName); try { User user = execQuerySql(connection,sqlStr,parm_link); if ( user != null ){ this.queryResult = user.toString(); //--將結果寫到redis System.out.println(Thread.class.getName()+" parm " + this.parmName +" set a vlaue to redis!"); jedis.set(this.parmName,this.queryResult); } } catch (SQLException e) { e.printStackTrace(); } } } } @Test public void test() throws InterruptedException { //衝突的記錄 String cfkName = "liming01"; //第一條請求-執行更新操作的執行緒 UpdateRedisDataBaseThread drud = new UpdateRedisDataBaseThread(cfkName,"liming01",66); //併發第二條請求 - 執行查詢操作的執行緒 SelectThread udbt = new SelectThread(cfkName); new Thread(drud).start(); //休眠一秒-模擬其它操作 Thread.sleep(2000); //第二個執行緒開始查詢 new Thread(udbt).start(); //主執行緒休眠10s Thread.sleep(10000);//休眠20s } }
相關推薦
多執行緒模擬高併發情況redis 與資料庫快取不一致
import com.mysql.jdbc.Connection; import entity.User; import org.junit.Test; import redis.clients.jedis.Jedis; import java.sql.*; import
使用Redis中介軟體解決商品秒殺活動中出現的超賣問題(使用Java多執行緒模擬高併發環境)
開發十年,就只剩下這套架構體系了! >>>
多執行緒,高併發的情況下操作redis當中的資料,如何加鎖?
多個執行緒同時去操作Redis當中的資料,假如不加鎖的情況下,會出現資料重複的問題。假如需要每次都只有一條執行緒去操作Redis當中的資料,需要給操作加上鎖。 但是去網上一搜,網上給Redis加鎖的機制都是利用Redis的setnx自身的方法去加鎖,但是這樣
同步、非同步、多執行緒、高併發不再混淆!
高併發:“短時間內遇到大量操作請求”的情況。 多執行緒:多執行緒就是指一個程序中同時有多個執行緒正在執行。其目的就是當某個執行緒很耗時的時候使用多執行緒,可以在將耗時任務放在後臺繼續執行的同時,同時執行其他操作,達到提升效率,優化使用者體驗的效果。 多執行緒是完成高併發任
Java多執行緒:解決高併發環境下資料插入重複問題
1.背景描述 應用框架:Spring + SpringMVC + Hibernate 資料庫:Oracle11g 一家文學網站向我係統推多執行緒低併發推送資料,我這邊觀察日誌和資料庫,發現有
多執行緒WEB高併發壓力測試軟體JMeter
一、 Apache JMeter工具 1)簡介 JMeter——一個100%的純java桌面應用,它是 Apache組織的開放原始碼專案,它是功能和效能測試的工具。JMeter可以用於測試靜態或者動態資源的效能(檔案、Servlets、Perl指令碼、java物
多執行緒、高併發
執行緒與程序 執行緒是CPU排程和分配的基本單位,程序是資源分配和排程的基本單位 一個程序中可以包括多個執行緒,執行緒共享整個程序的資源(暫存器、堆疊、上下文),執行緒間要進行同步和互斥 區別
JUC多執行緒及高併發
一、請你談談對volatile的理解 Package java.util.concurrent---> A
JUC多執行緒及高併發面試題
JUC多執行緒及高併發 [TOC] 一、請你談談對volatile的理解 Package java.util.concurre
JAVA多執行緒(四) Executor併發框架向RabbitMQ推送訊息
github程式碼地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo 假設一個需求使用者點選某個頁面,我們後臺需要向MQ推送信資訊 1,模擬的MQ服務,我這邊使用RabbitMQ (關於MQ 傳送和監聽訊息可以
多執行緒(十): 併發中集合ConcurrentHashMap
public class HashTest { static Map<String, String> map = new HashMap<>(); public static void main(String[] args) {
java:Map集合模擬鬥地主,多執行緒模擬搶地主 例項
原始碼如下: package selfpractice.day4; import java.util.*; //多執行緒模擬搶地,重點程式碼位於loot()方法內 public class Practice_Poker { public static void main(S
多執行緒模擬實現生產者/消費者模型
多執行緒模擬實現生產者/消費者模型 package com.chow.queue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java
Java多執行緒(二)Java併發工具包concurrent例項簡述
傳統的多執行緒並沒有提供高階特性,例如:訊號量、執行緒池和執行管理器等,而這些特性恰恰有助於建立強大的併發程式。新的Fork/Join框架針對當前的多核系統,也提供了並行程式設計的可能。這塊的內容是java多執行緒資訊量最大的一部分內容,本篇部落格循序漸進的,首
Nodejs探祕:深入理解單執行緒實現高併發原理
前言 從Node.js進入我們的視野時,我們所知道的它就由這些關鍵字組成 事件驅動、非阻塞I/O、高效、輕量,它在官網中也是這麼描述自己的: Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript e
多執行緒模擬搶紅包
今天有朋友問我一道面試題,有5個人搶5個紅包,可重複搶,用多執行緒程式實現,實現方式有多種,分享一下我的思路:應用了阻塞佇列的特性 /** * Created by zhanglinqiang on 2016/6/23. */ public class MyTest
JMeter壓力測試(流程骨架/搶紅包舉例實戰/多場景多執行緒組混合併發/HTTPS請求)
效能測試裡面包含三個測試:基準測試、負載測試、壓力測試。基準測試就是用一個虛擬使用者(UV)進行一個對被測系統/物件的操作負載測試就是慢慢不斷地加UV壓力測試就是長時間連續執行系統給系統性能造成的影響,一直到測出問題為止一、JMeter進行HTTP協議介面的壓力測試1.新增執
關於多執行緒處理資料併發問題處理
資料量多時需要要多執行緒處理,尤其在叢集環境下很可能發生資源競爭的情況,此時就需要謹慎的對資料加鎖,如果加鎖出了問題,也是個麻煩事。 為安全考慮,一般處理這種問題有幾個步驟: 為此個業務加開關,如果出現問題,將開關關閉。但是遇到一些緊急問題,開關關閉會影響業務,這時就需要走
JAVA學習之路(多執行緒)---模擬售票(細解)
首先看題目描述: 假設有火車票100張,建立4個執行緒模擬4個售票點,每100ms售出一張,打印出售票過程,格式如下: 視窗3:賣出第100張票 視窗4:賣出第99張票 ............ ............ 簡單的思路就是建立一個類,首先肯定要去繼承Thread。開啟執行
多執行緒基礎 Java併發1
目錄 執行緒和程序概念 同步和非同步概念 多執行緒建立方式 繼承Thread類(不推薦) 實現runnable介面,重寫run方法 使用匿名內部類 多執行緒的執行狀態 守護執行緒、非守護執行緒 join方法() 優先順序 執行緒安全