采用多线程对数据库读写引发冲突

采用多线程对数据库读写引发冲突,第1张

我只说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数据库等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9314523.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存