java 多线程存储数据库

java 多线程存储数据库,第1张

以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();

        }

    }

}

以mysql来说,可能出现脏读、不可重复读以及幻读,mysql默认设置是可重复读,即一次事务中不会读取到不同的数据。

可以做如下 *** 作:

1)打开两个客户端,均设置为RR;

2)在一个事务中,查询某个 *** 作查到某份数据;比如是某个字段version=1存在数据;

3)在另一个事务中,删除这份version=1的数据;删除后,在2所属的事务中查询数据是没有变化的,还是存在version=1的数据;

4)当我们在2所属的事务中继续更新数据,那么会发现更新不了,明明我们就看到了这份version=1的数据;

缓存一致性:

缓存一致,与什么一致?是与数据库一致,对外查询每个时刻一致;所以在针对于缓存与数据库之间该先更新哪一个呢?可能有人觉得我先更新数据库,再更新缓存不就行了吗?但是有想过个问题吗?

当用户已经支付成功了,更新到数据库,但是呢?你还在缓存中显示未支付,在用户点击频率很高并且数据库压力过大,来不及同步到缓存时,那你是不是很尴尬,这就是典型的不一致了。此时用户再支付,那你又告诉他已经支付了,那他会把你骂死的

那该怎么来做呢?我们可以这样,先更新缓存再更新数据库,那么存在什么问题呢?

1)缓存更新成功,但是数据库更新失败,而被其它的并发线程访问到

2)缓存淘汰成功,但是数据库更新失败,这也会引发后期数据不一致

一、学习前的准备工作

java语言一般用于大型的服务器程序开发,所有有必要了解如下内容:Unix开发环境Unix系统原理、Unix开发环境、Unix常用命令。熟练掌握Unix常用命令;熟练构建下的Java开发环境。

二、Java语言基础的学习阶段学习

任何一门语言都要打好基础,曾经学过高级程序语言(C,C++等)来说,java语言基础有自己的特点,但是基本规律都是相通的,如:算法基础、常用数据结构、企业编程规范。掌握常见的数据结构和实用算法;培养良好的企业级编程习惯。

三、面向对象语言的共性

Java面向对象面向对象特性:封装、继承、多态等。掌握面向对象的基本原则以及在编程实践中的意义;掌握Java面向对象编程基本实现原理。

 四、JDK核心API语言核心包、异常处理、常用工具包、集合框架

熟练掌握JDK核心API编程技术;理解API设计原则;具备熟练的阅读API文档的能力;JavaSE核心异常处理、多线程基础、IO系统、网络编程、Swing组件、JVM性能调优(JVM内存结构剖析、GC分析及调优、JVM内存参数优化)、Java泛型、JDK新特性。熟练掌握JavaSE核心内容,特别是IO和多线程;初步具备面向对象设计和编程的能力;掌握基本的JVM优化策略。XMLXML语法、XML解析(SAX、DOM)、Dom4j组件、Digester组件。熟练掌握XML语法规则;理解DOM模型;熟悉Java对XML的各种解析方式。

五、SQL语言SQL语句基础和提高、SQL语句调优

熟练的掌握SQL语句;掌握一定的数据库查询技巧及SQL语句优化技巧。Oracle数据库开发Oracle体系结构及系统管理、Oracle数据库高级编程、数据库设计基础。掌握Oracle体系结构及核心编程技术。

六、连接数据库:JDBCJDBC核心API(Connection、Statement、ResultSet)、JDBC优化技术(缓存技术、批处理技术、连接池技术)

理解JDBC作为规范的设计原则;熟练掌握JDBCAPI;具备使用JDBC对数据库进行高效访问的能力。

七、软件工程基础软件过程和软件活动

需求设计、概要设计、详细设计基本原则和文档规范;配置管理的基本概念和必要性;CVS基本 *** 作;Ant简介理解软件过程的普遍概念和基本的软件活动;理解迭代的意义;掌握Ant、CVS等常用配置管理及部署工具。

八、OOAD及设计模式面向对象基本设计原则、工厂模式、策略模式、适配器模式、代理模式等、门面模式

理解面向对象设计的一般原则;理解重用的意义;掌握常见的设计模式。

九、HTML/CSSHTML基本文档结构、掌握CSS基础语法、关于HTML文档块、链接、列表、表格、表单等

掌握

十、Ajax基础、XHR对象、Ajax设计模式、JSON技术

掌握Ajax的基本通信原理;掌握基于XML和JSON的Ajax数据规则。

十一、JavaScript框架JQuery、JQuery插件、DWR

掌握JQuery核心API;了解JQuery基本设计原则;了解多种JQuery插件;掌握DWR的基本原理及应用技巧。

十二、ssh三大框架的学习

这是企业实际应用的框架模型:

1,Struts216Struts2核心控制流程、Ognl、Action、Interceptor、,Result、FreeMarker、Struts2标记库、Struts2扩展、Struts2应用技巧(输入验证、消息国际化、文件上传和下载、防止重复提交等)。熟练掌握Struts2核心要件,特别是Interceptor和Result;掌握基于模板技术的Struts2UI组件;掌握基于Ognl的数据共享方式、掌握Struts2各种定制及扩展方式;熟练掌握基于Struts2的Web开发技巧。

2,Hibernate321ORM概念、Hibernate核心API、Hibernate实体映射技术、Hibernate关系映射技巧、HQL查询、OSCache及Hibernate缓存技术。重点掌握Hibernate多种关联映射技巧及其实用背景,做到在合适的时候使用合适的关联方式;掌握多种Hibernate查询技巧及优化技术。

3,Spring25SpringIoc基础、Ioc注入技巧、对象高级装配(自动装配、模板装配、组件扫描特性、FactoryBean、对象生命周期)、SpringAOP原理、AspectJ、SpringJDBC支持、Spring事务及安全管理;Spring整合Hibernate、Spring整合Struts、SpringMVC简介。深入理解Ioc和AOP的基本原理和实现方式;熟练掌握SpringIoc及AOP实现方式;熟练掌握Spring事务管理;熟练掌握Spring与其他组件的整合技术。

你把原来程序中直接读的地方,改成调用上面的函数,由该函数统一读行。这样,不管是你有 N 个线程,还是一个线程,都不会发生读的行重复,或者读的行不完整的现象了。

为了充分利用多线程读取,就需要把文件划分成多个区域,供每个线程读取。那么就需要有一个算法来计算出每个线程读取的开始位置和结束位置。那么首先根据配置的线程数和文件的总长度计,算出每个线程平均分配的读取长度。

但是有一点,由于文件是纯文本文件,必须按行来处理,如果分割点在某一行中间,那么这一行数据就会被分成两部分,分别由两个线程同时处理,这种情况是不能出现的。所以各个区域的结束点上的字符必须是换行符。第一个区域的开始位置是0,结束位置首先设为(文件长度/线程数),如果结束点位置不是换行符,就只能加1,直到是换行符位置。

如果多线程 *** 作,那么需要保证多个线程 *** 作同一个对象,此外请保证先有线程放进内容,其他线程才能拿出数据。

附上具体参考代码:

public class Test{

public static void main(String args[])throws Exception{

File file = new File("D:\\Testjava");//Text文件

BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件

String s = null;

while((s = brreadLine())!=null){//使用readLine方法,一次读一行

Systemoutprintln(s);

}

brclose();;

}

}

你这个首先得分开。

第一部分:你有很多线程在往数据池里面写入数据。那么,你的线程只管写数据,不用理会其他的数据。

第二部分:你的另外的线程(这里可以用spring的job定时器启动),这部分只管往数据库写入数据,至于写入的条件,你可以判断数据池的数据是否达到写入的标准。这里的线程可以配置为启动一次就一直运行,或者是隔多少秒继续运行。这样可以提高效率。

第三部分:数据池,这里的数据池一定要第一部分和第二部分的线程都能够访问,并且是唯一的。你可以写一个公用的类来进行控制。

大致就是这样的。

优化建议:

1 在你的代码里大点评测下 每个 *** 作花的时间 譬如 dom4j解析花了多久, 存储到数据库花了多久等等

2 评测哪些地方可以并行 *** 作以提高CPU利用率;

3 数据库 *** 作部分也可以做适当优化, 譬如批量提交可以显著提高插入速度, 譬如去除索引/主键后插入等;

4 不同机器的IO速度是不同的, 因此应该能提供运行时的任务调度参数化, 譬如多少个dom4j解析线程, 入库的批量数量等;

以上就是关于java 多线程存储数据库全部的内容,包括:java 多线程存储数据库、java多线程下如何保证数据的一致性、零基础学习Java编程需要知道什么等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存