我只说oracle的吧,insert的时候一般是会加行级写锁,一般不会升级到表级锁,多个线程之间处理的数据是否存在抢占了呢如果是单纯的insert into 不同的信息是不会冲突的
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 = NACommonExtensionsGetDatabaseName<T>();
if (stringIsNullOrEmpty(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 = NACommonExtensionsGetConnectionString<T>();
int poolSize = NACommonExtensionsGetConnectionPoolSize<T>();
lock (locker)
{
for (int i = 0; i < poolSize; ++i)
{
SqlConnection conn = new SqlConnection(strconn);
connOpen();
ConnectionsAdd(databaseName + "_" + iToString(), conn);
connClose();
}
}
return Connections[FindFreeSqlConnection(databaseName)];
}
}
private static string FindFreeSqlConnection(string databaseName)
{
IEnumerable<string> connKeys = ConnectionsKeysWhere(item => itemStartsWith(databaseName));
if (connKeys != null && connKeysCount() > 0)
{
foreach (string key in connKeys)
{
if (Connections[key]State == ConnectionStateClosed)
return key;
}
}
return null;
}
}
附加上其中用到的三个方法:
internal static int GetConnectionPoolSize<T>() where T : class, new()
{
string database = GetDatabaseName<T>();
string[] poolSizeArray = ConfigurationManagerAppSettings["ConnectionsPoolSize"]Split('|');
if (poolSizeArray != null)
{
foreach (string sizeItem in poolSizeArray)
{
string[] sizeItemArray = sizeItemSplit(':');
if (database == sizeItemArray[0])
return intParse(sizeItemArray[1]);
}
}
return 50;
}
public static string GetConnectionString<T>() where T : class, new()
{
string tableName = GetTableName<T>();
string[] databaseArray = ConfigurationManagerAppSettings["DatabaseArray"]Split('|');
if (databaseArray != null)
{
foreach (string database in databaseArray)
{
string tableNameList = ConfigurationManagerAppSettings[database];
string[] tables = ConfigurationManagerAppSettings[database]Split('|');
if (tables != null && tablesLength > 0)
if (tablesContains(tableName))
return ConfigurationManagerConnectionStrings[database]ConnectionString;
}
}
return stringEmpty;
}
public static string GetDatabaseName<T>() where T : class, new()
{
string tableName = GetTableName<T>();
string[] databaseArray = ConfigurationManagerAppSettings["DatabaseArray"]Split('|');
if (databaseArray != null)
{
foreach (string database in databaseArray)
{
string tableNameList = ConfigurationManagerAppSettings[database];
string[] tables = ConfigurationManagerAppSettings[database]Split('|');
if (tables != null && tablesLength > 0)
if (tablesContains(tableName))
return database;
}
}
return stringEmpty;
}
错。连接数据库要连接池,就是connection对象要放在一个LinkedList里面,然后每个线程一个。这个这个List被封装在一个单例模式的对象里。线程要是共享connection,要是搞起并发来,一下子就挂了。
以mysql为数据库写的一个粗陋的demo,你参考一下,希望不会因为代码过多被百度吞了——
import javasqlConnection;import javasqlDriverManager;
import javasqlPreparedStatement;
import javasqlResultSet;
import javasqlSQLException;
import javautilArrayList;
import javautilList;
public class Test {
public static void main(String[] args) {
allotThread();
}
/
将100条数据分成10份并启动10个线程分别 *** 作
/
public static void allotThread() {
List<String[]> datas = buildDatas();
for (int i=0; i<100; i+=10) {
List<String[]> tenDatas = datassubList(i, i + 10);
insertData(tenDatas);
}
}
/
创建100条模拟数据
@return
/
public static List<String[]> buildDatas() {
List<String[]> datas = new ArrayList<String[]>();
for (int i=0; i<100; i++) {
String[] data = {"id " + i, "name " + i};
datasadd(data);
}
return datas;
}
/
启动线程进行数据插入 *** 作
@param tenDatas
/
public static void insertData(final List<String[]> tenDatas) {
new Thread(new Runnable() {
public void run() {
String sql = "insert into testtable (id, name) values (, )";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
connsetAutoCommit(false);
pstmt = getPstmt(conn, sql);
for (String[] data : tenDatas) {
pstmtsetString(1, data[0]);
pstmtsetString(2, data[1]);
pstmtaddBatch();
}
pstmtexecuteBatch();
conncommit();
connsetAutoCommit(true);
} catch (SQLException e) {
eprintStackTrace();
rollback(conn);
} catch (ClassNotFoundException e) {
eprintStackTrace();
} finally {
close(pstmt);
close(conn);
}
}
})start();
}
public static Connection getConnection() throws SQLException, ClassNotFoundException {
ClassforName("commysqljdbcDriver");
String dbUrl = "jdbc:mysql://localhost/testuseUnicode=true&characterEncoding=UTF-8";
Connection conn = DriverManagergetConnection(dbUrl, "root", "tooeasy");
return conn;
}
public static PreparedStatement getPstmt(Connection conn, String sql) throws SQLException, ClassNotFoundException {
PreparedStatement pstmt = connprepareStatement(sql);
return pstmt;
}
public static void rollback(Connection conn) {
try {
if (null != conn) {
connrollback();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(Connection conn) {
try {
if (null != conn) {
connclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(PreparedStatement pstmt) {
try {
if (null != pstmt) {
pstmtclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (null != rs) {
rsclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
}
以上就是关于采用多线程对数据库读写引发冲突全部的内容,包括:采用多线程对数据库读写引发冲突、多线程 连接数据库,C#多线程写数据库、如何用多线程连接多个mssql数据库等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)