A. 線程池向ifmx資料庫中插入數據時卡死 怎麼回事
zhezhelin
線程池和資料庫連接池的原理
本文我們簡單介紹了一下資料庫連接池和線程池的工作原理,希望能夠對您有所幫助。
當客戶端請求的數據量比較大的時候,使用線程池可以節約大量的系統資源,使得更多的CPU時間和內存可以高效地利用起來。而資料庫連接池的使用則將大大提高程序運行效率,同時,我們可以通過其自身的管理機制來監視資料庫連接的數量、使用情況等。本文我們主要就介紹一下線程池和資料庫連接池的原理,接下來我們一起來了解一下這一部分內容。
線程池的原理:
其實線程池的原理很簡單,類似於操作系統中的緩沖區的概念,它的流程如下:先啟動若干數量的線程,並讓這些線程都處於睡眠狀態,當客戶端有一個新請求時,就會喚醒線程池中的某一個睡眠線程,讓它來處理客戶端的這個請求,當處理完這個請求後,線程又處於睡眠狀態。可能你也許會問:為什麼要搞得這么麻煩,如果每當客戶端有新的請求時,我就創建一個新的線程不就完了?這也許是個不錯的方法,因為它能使得你編寫代碼相對容易一些,但你卻忽略了一個重要的問題?那就是性能!就拿我所在的單位來說,我的單位是一個省級數據大集中的銀行網路中心,高峰期每秒的客戶端請求並發數超過100,如果為每個客戶端請求創建一個新線程的話,那耗費的CPU時間和內存將是驚人的,如果採用一個擁有200個線程的線程池,那將會節約大量的系統資源,使得更多的CPU時間和內存用來處理實際的商業應用,而不是頻繁的線程創建與銷毀。
資料庫連接池的原理:
資料庫連接是一種關鍵的有限的昂貴的資源,這一點在多用戶的網頁應用程序中體現得尤為突出。
一個資料庫連接對象均對應一個物理資料庫連接,每次操作都打開一個物理連接,使用完都關閉連接,這樣造成系統的性能低下。 資料庫連接池的解決方案是在應用程序啟動時建立足夠的資料庫連接,並講這些連接組成一個連接池(簡單說:在一個「池」里放了好多半成品的資料庫聯接對象),由應用程序動態地對池中的連接進行申請、使用和釋放。對於多於連接池中連接數的並發請求,應該在請求隊列中排隊等待。並且應用程序可以根據池中連接的使用率,動態增加或減少池中的連接數。
連接池技術盡可能多地重用了消耗內存地資源,大大節省了內存,提高了伺服器地服務效率,能夠支
B. 如何在多線程操作資料庫
通常,最好避免鎖定 public 類型或鎖定不受應用程序控制的對象實例。例如,如果該實例可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。這可能導致死鎖,即兩個或更多個線程等待釋放同一對象。出於同樣的原因,鎖定公共數據類型(相比於對象)也可能導致問題。鎖定字元串尤其危險,因為字元串被公共語言運行庫 (CLR)「暫留」。這意味著整個程序中任何給定字元串都只有一個實例,就是這同一個對象表示了所有運行的應用程序域的所有線程中的該文本。因此,只要在應用程序進程中的任何位置處具有相同內容的字元串上放置了鎖,就將鎖定應用程序中該字元串的所有實例。因此,最好鎖定不會被暫留的私有或受保護成員。某些類提供專門用於鎖定的成員。例如,Array 類型提供 SyncRoot。許多集合類型也提供 SyncRoot。
C. 大家是如何處理很多線程連接資料庫連接的
連接資料庫要連接池,就是connection對象要放在一個LinkedList裡面,然後每個線程一個。這個這個List被封裝在一個單例模式的對象里。線程要是共享connection,要是搞起並發來,一下子就掛了。
D. java 多線程操作資料庫
//將資料庫中的數據條數分段
publicvoiddivision(){
//獲取要導入的總的數據條數
Stringsql3="SELECTcount(*)FROM[CMD].[dbo].[my1]";
try{
pss=cons.prepareStatement(sql3);
rss=pss.executeQuery();
while(rss.next()){
System.out.println("總記錄條數:"+rss.getInt(1));
sum=rss.getInt(1);
}
//每30000條記錄作為一個分割點
if(sum>=30000){
n=sum/30000;
resie=sum%30000;
}else{
resie=sum;
}
System.out.println(n+""+resie);
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
線程類
publicMyThread(intstart,intend){
this.end=end;
this.start=start;
System.out.println("處理掉余數");
try{
System.out.println("--------"+Thread.currentThread().getName()+"------------");
Class.forName(SQLSERVERDRIVER);
System.out.println("載入sqlserver驅動...");
cons=DriverManager.getConnection(CONTENTS,UNS,UPS);
stas=cons.createStatement();
System.out.println("連接SQLServer資料庫成功!!");
System.out.println("載入mysql驅動.....");
Class.forName(MYSQLDRIVER);
con=DriverManager.getConnection(CONTENT,UN,UP);
sta=con.createStatement();
//關閉事務自動提交
con.setAutoCommit(false);
System.out.println("連接mysql資料庫成功!!");
}catch(Exceptione){
e.printStackTrace();
}
//TODOAuto-generatedconstructorstub
}
publicArrayList<Member>getAll(){
Membermember;
Stringsql1="select*from(selectrow_number()over(orderbypmcode)asrowNum,*"+
"from[CMD].[dbo].[my1])astwhererowNumbetween"+start+"and"+end;
try{
System.out.println("正在獲取數據...");
allmembers=newArrayList();
rss=stas.executeQuery(sql1);
while(rss.next()){
member=newMember();
member.setAddress1(rss.getString("address1"));
member.setBnpoints(rss.getString("bnpoints"));
member.setDbno(rss.getString("dbno"));
member.setExpiry(rss.getString("expiry"));
member.setHispoints(rss.getString("hispoints"));
member.setKypoints(rss.getString("kypoints"));
member.setLevels(rss.getString("levels"));
member.setNames(rss.getString("names"));
member.setPmcode(rss.getString("pmcode"));
member.setRemark(rss.getString("remark"));
member.setSex(rss.getString("sex"));
member.setTelephone(rss.getString("telephone"));
member.setWxno(rss.getString("wxno"));
member.setPmdate(rss.getString("pmdate"));
allmembers.add(member);
//System.out.println(member.getNames());
}
System.out.println("成功獲取sqlserver資料庫數據!");
returnallmembers;
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
System.out.println("獲取sqlserver資料庫數據發送異常!");
e.printStackTrace();
}
try{
rss.close();
stas.close();
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnnull;
}
publicvoidinputAll(ArrayList<Member>allmembers){
System.out.println("開始向mysql中寫入");
Stringsql2="insertintotest.my2values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try{
ps=con.prepareStatement(sql2);
System.out.println("-------------------------等待寫入數據條數:"+allmembers.size());
for(inti=0;i<allmembers.size();i++){
ps.setString(1,allmembers.get(i).getPmcode());
ps.setString(2,allmembers.get(i).getNames());
//System.out.println(allmembers.get(i).getNames());
ps.setString(3,allmembers.get(i).getSex());
ps.setString(4,allmembers.get(i).getTelephone());
ps.setString(5,allmembers.get(i).getAddress1());
ps.setString(6,allmembers.get(i).getPmdate());
ps.setString(7,allmembers.get(i).getExpiry());
ps.setString(8,allmembers.get(i).getLevels());
ps.setString(9,allmembers.get(i).getDbno());
ps.setString(10,allmembers.get(i).getHispoints());
ps.setString(11,allmembers.get(i).getBnpoints());
ps.setString(12,allmembers.get(i).getKypoints());
ps.setString(13,allmembers.get(i).getWxno());
ps.setString(14,allmembers.get(i).getRemark());
//插入命令列表
//ps.addBatch();
ps.executeUpdate();
}
//ps.executeBatch();
con.commit();
ps.close();
con.close();
this.flag=false;
System.out.println(Thread.currentThread().getName()+"--->OK");
}catch(SQLExceptione){
//TODOAuto-generatedcatchblock
System.out.println("向mysql中更新數據時發生異常!");
e.printStackTrace();
}
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
while(true&&flag){
this.inputAll(getAll());
}
}
E. 大量實時數據如何寫入到資料庫
如果是實時的數據,自己寫程序總數最方便的。
常見解決方案:所有保存任務扔到一個隊列,由後台的線程池執行隊列中的保存任務。
如果會java或者C#這種高級語言,啥都好辦,隊列可以放在內存中,如果只會shell或者php,可以用文件作為隊列。
如果不會寫程序,可以考慮在內存檔中創建一個資料庫,將實時數據寫到這里,作為緩存,然後通過類似mysql主從資料庫這種結構將數據同步到硬碟上,不過這種方案設置起來非常麻煩。
F. 多線程訪問資料庫問題
這個要看情況。
不同的資料庫情況不一樣。
一般說來是可以每個線程使用一個連接的(有時候會出現很難查找的奇怪問題)
保險一點還是共用一個連接 互斥佔用。
G. 多線程 連接資料庫,C#多線程寫資料庫
多線程連接資料庫的連接池類:
public static class ConnectionPool
{
private static object locker = new object();
private static Dictionary<string, SqlConnection> Connections = null;
public static SqlConnection GetConnection<T>() where T : class, new()
{
string databaseName = NA.Common.Extensions.GetDatabaseName<T>();
if (string.IsNullOrEmpty(databaseName))
return null;
if (Connections == null)
{
lock (locker)
{
Connections = new Dictionary<string, SqlConnection>();
}
}
string connKey = FindFreeSqlConnection(databaseName);
if (connKey != null)
return Connections[connKey];
else
{
string strconn = NA.Common.Extensions.GetConnectionString<T>();
int poolSize = NA.Common.Extensions.GetConnectionPoolSize<T>();
lock (locker)
{
for (int i = 0; i < poolSize; ++i)
{
SqlConnection conn = new SqlConnection(strconn);
conn.Open();
Connections.Add(databaseName + "_" + i.ToString(), conn);
conn.Close();
}
}
return Connections[FindFreeSqlConnection(databaseName)];
}
}
private static string FindFreeSqlConnection(string databaseName)
{
IEnumerable<string> connKeys = Connections.Keys.Where(item => item.StartsWith(databaseName));
if (connKeys != null && connKeys.Count() > 0)
{
foreach (string key in connKeys)
{
if (Connections[key].State == ConnectionState.Closed)
return key;
}
}
return null;
}
}
附加上其中用到的三個方法:
internal static int GetConnectionPoolSize<T>() where T : class, new()
{
string database = GetDatabaseName<T>();
string[] poolSizeArray = ConfigurationManager.AppSettings["ConnectionsPoolSize"].Split('|');
if (poolSizeArray != null)
{
foreach (string sizeItem in poolSizeArray)
{
string[] sizeItemArray = sizeItem.Split(':');
if (database == sizeItemArray[0])
return int.Parse(sizeItemArray[1]);
}
}
return 50;
}
public static string GetConnectionString<T>() where T : class, new()
{
string tableName = GetTableName<T>();
string[] databaseArray = ConfigurationManager.AppSettings["DatabaseArray"].Split('|');
if (databaseArray != null)
{
foreach (string database in databaseArray)
{
string tableNameList = ConfigurationManager.AppSettings[database];
string[] tables = ConfigurationManager.AppSettings[database].Split('|');
if (tables != null && tables.Length > 0)
if (tables.Contains(tableName))
return ConfigurationManager.ConnectionStrings[database].ConnectionString;
}
}
return string.Empty;
}
public static string GetDatabaseName<T>() where T : class, new()
{
string tableName = GetTableName<T>();
string[] databaseArray = ConfigurationManager.AppSettings["DatabaseArray"].Split('|');
if (databaseArray != null)
{
foreach (string database in databaseArray)
{
string tableNameList = ConfigurationManager.AppSettings[database];
string[] tables = ConfigurationManager.AppSettings[database].Split('|');
if (tables != null && tables.Length > 0)
if (tables.Contains(tableName))
return database;
}
}
return string.Empty;
}
H. 請教如何進行多線程連接資料庫並寫入數據
#include <QCoreApplication>
#include "thread.h"
#include <QVector>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVector<Thread*> vector;
Thread *thread;
//創建多個線程,並start
for(int i=0;i<10;i++){
thread=new Thread;
vector.append(thread);
thread->set(i);
thread->start();
}
//等待所有線程執行完,然後刪除線程
foreach(thread,vector){
thread->wait();
}
foreach(thread,vector){
delete thread;
}
return a.exec();
}
-------------------------------------------------------------------------------------------------
#include "thread.h"
Thread::Thread(QObject *parent) : QThread(parent)
{
}
void Thread::run()
{
begin();
}
//為每個線程創建一個連接名
void Thread::set(int a)
{
connectionName=QString::number(a);
}
void Thread::connectionDatabase(QString dbName)
{
QSqlDatabasedb=QSqlDatabase::addDatabase("QMYSQL",connectionName);
db.setHostName("localhost");
db.setDatabaseName(dbName);
db.setUserName("root");
db.setPassword("");
if(!db.open())
qDebug()<<"db open fail";
}
void Thread::begin()
{
QString dbName="learnsql";
connectionDatabase(dbName);
QSqlDatabase db=QSqlDatabase::database(connectionName);
db.transaction(); //開啟事物
QSqlQuery query(db);
//向表student中插入10000條數據
for(int i=1;i<=10000;i++){
query.exec("insert into student values(1)");
}
db.commit(); //提交事物
}
I. java 多線程 寫入資料庫 數據池
你這個首先得分開。
第一部分:你有很多線程在往數據池裡面寫入數據。那麼,你的線程只管寫數據,不用理會其他的數據。
第二部分:你的另外的線程(這里可以用spring的job定時器啟動),這部分只管往資料庫寫入數據,至於寫入的條件,你可以判斷數據池的數據是否達到寫入的標准。這里的線程可以配置為啟動一次就一直運行,或者是隔多少秒繼續運行。這樣可以提高效率。
第三部分:數據池,這里的數據池一定要第一部分和第二部分的線程都能夠訪問,並且是唯一的。你可以寫一個公用的類來進行控制。
大致就是這樣的。