精华内容
下载资源
问答
  • 使用多线程提高代码运行速度

    千次阅读 2017-03-29 15:23:41
    这时候需要写大量代码,查询,修改数据库,中间会夹杂着大量的业务逻辑判断,这样无疑造成了代码执行速度慢,为了程序能更快的运行,当然就需要我们来优化了,优化的思路有很多,今天主要讲运用多线程来进行优化。...

    第一次写博客,心情还是比较激动的,写博客的目的主要还是积累下工作中遇到的各种问题以及解决问题的思路。。。

    在工作中,难免会遇到业务逻辑比较复杂的情况,这时候需要写大量代码,查询,修改数据库,中间会夹杂着大量的业务逻辑判断,这样无疑造成了代码执行速度慢,为了程序能更快的运行,当然就需要我们来优化了,优化的思路有很多,今天主要讲运用多线程来进行优化。。。

    多线程在单核计算机中是不能起到提高代码速度的作用,因为单核计算机在某一时刻只能执行一条主线,但是在今天很多计算机都具备双核或多核,服务器的核更多,这样启动多线程的时候,多个核就能同时执行多条线,这样就能起到提高代码运行速度的作用。。

    之前未启用多线程,执行这段代码要3分钟多,用了多线程后大概30秒,就能把这段代码执行完毕,明显提高了运行速度。。。

    展开全文
  • 数据库中一张表有千万条记录,现在有一个请求,需要查询所有记录,在不变动数据库的前提下,在写程序的时候,如何提高查询速度?是用多线程吗,如果用多线程,具体怎样实现呢?希望得到大家的指点,谢谢大家!
  • 数据库中数据量很大的时候,如果仅仅依靠缩小时间段, 则划分太麻烦。由于在做进度条显示的时候,经常...引用:在数据库表中,使用索引可以大大提高查询速度。假如我们创建了一个testIndex表:CREATE TABLE testIndex

    数据库中数据量很大的时候,如果仅仅依靠缩小时间段, 则划分太麻烦。由于在做进度条显示的时候,经常显示不出进度条上的static控件的文字,刷新太频繁,采用多线程查询,当后来,每个连接值能对应一个查询,放弃

    目前看来,优化查询速度的方法主要靠索引完成。

    引用:

    在数据库表中,使用索引可以大大提高查询速度。

    假如我们创建了一个testIndex表:
    CREATE TABLE testIndex(i_testID INT NOT NULL,vc_Name VARCHAR(16) NOT NULL);

    我们随机向里面插入了1000条记录,其中有一条
        i_testID    vc_Name
          555    erquan
        
    在查找vc_Name="erquan"的记录
    SELECT * FROM testIndex WHERE vc_Name=@#erquan@#;
    时,如果在vc_Name上已经建立了索引,MySql无须任何扫描,即准确可找到该记录!相反,MySql会扫描所有记录,即要查询1000次啊~~可以索引将查询速度提高100倍。

    一、索引分单列索引和组合索引
       单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。
       组合索引:即一个索包含多个列。

    二、介绍一下索引的类型

        1.普通索引。
          这是最基本的索引,它没有任何限制。它有以下几种创建方式:
          (1)创建索引:CREATE INDEX indexName ON tableName(tableColumns(length));如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB 和 TEXT 类型,必须指定length,下同。
          (2)修改表结构:ALTER tableName ADD INDEX [indexName] ON (tableColumns(length))
          (3)创建表的时候直接指定:CREATE TABLE tableName ( [...], INDEX [indexName] (tableColumns(length)) ;
       
        2.唯一索引。
           它与前面的"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
           (1)创建索引:CREATE UNIQUE INDEX indexName ON tableName(tableColumns(length))
          (2)修改表结构:ALTER tableName ADD UNIQUE [indexName] ON (tableColumns(length))
          (3)创建表的时候直接指定:CREATE TABLE tableName ( [...], UNIQUE [indexName] (tableColumns(length));

         3.主键索引
           它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:CREATE TABLE testIndex(i_testID INT NOT NULL AUTO_INCREMENT,vc_Name VARCHAR(16) NOT NULL,PRIMARY KEY(i_testID)); 当然也可以用ALTER命令。
           记住:一个表只能有一个主键。

          4.全文索引
            MySQL从3.23.23版开始支持全文索引和全文检索。这里不作讨论,呵呵~~

        删除索引的语法:DROP INDEX index_name ON tableName

    三、单列索引和组合索引

        为了形象地对比两者,再建一个表:
        CREATE TABLE myIndex ( i_testID INT NOT NULL AUTO_INCREMENT, vc_Name VARCHAR(50) NOT NULL, vc_City VARCHAR(50) NOT NULL, i_Age INT NOT NULL, i_SchoolID INT NOT NULL, PRIMARY KEY (i_testID) );

        在这10000条记录里面7上8下地分布了5条vc_Name="erquan"的记录,只不过city,age,school的组合各不相同。
      来看这条T-SQL:
        SELECT i_testID FROM myIndex WHERE vc_Name=@#erquan@# AND vc_City=@#郑州@# AND i_Age=25;

        首先考虑建单列索引:
        在vc_Name列上建立了索引。执行T-SQL时,MYSQL很快将目标锁定在了vc_Name=erquan的5条记录上,取出来放到一中间结果集。在这个结果集里,先排除掉vc_City不等于"郑州"的记录,再排除i_Age不等于25的记录,最后筛选出唯一的符合条件的记录。

        虽然在vc_Name上建立了索引,查询时MYSQL不用扫描整张表,效率有所提高,但离我们的要求还有一定的距离。同样的,在vc_City和i_Age分别建立的单列索引的效率相似。

        为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将vc_Name,vc_City,i_Age建到一个索引里:
        ALTER TABLE myIndex ADD INDEX name_city_age (vc_Name(10),vc_City,i_Age);--注意了,建表时,vc_Name长度为50,这里为什么用10呢?因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。

        执行T-SQL时,MySQL无须扫描任何记录就到找到唯一的记录!!

        肯定有人要问了,如果分别在vc_Name,vc_City,i_Age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率一样吧?嘿嘿,大不一样,远远低于我们的组合索引~~虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。

        建立这样的组合索引,其实是相当于分别建立了
            vc_Name,vc_City,i_Age
            vc_Name,vc_City
            vc_Name
        这样的三个组合索引!为什么没有vc_City,i_Age等这样的组合索引呢?这是因为mysql组合索引"最左前缀"的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个T-SQL会用到:
        SELECT * FROM myIndex WHREE vc_Name="erquan" AND vc_City="郑州"
        SELECT * FROM myIndex WHREE vc_Name="erquan"
    而下面几个则不会用到:
        SELECT * FROM myIndex WHREE i_Age=20 AND vc_City="郑州"
        SELECT * FROM myIndex WHREE vc_City="郑州"

    四、使用索引
        到此你应该会建立、使用索引了吧?但什么情况下需要建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对 <,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE(后面有说明)才会使用索引。
        SELECT t.vc_Name FROM testIndex t LEFT JOIN myIndex m ON t.vc_Name=m.vc_Name WHERE m.i_Age=20 AND m.vc_City=@#郑州@#  时,有对myIndex表的vc_City和i_Age建立索引的需要,由于testIndex表的vc_Name开出现在了JOIN子句中,也有对它建立索引的必要。

        刚才提到了,只有某些时候的LIKE才需建立索引?是的。因为在以通配符 % 和 _ 开头作查询时,MySQL不会使用索引,如
        SELECT * FROM myIndex WHERE vc_Name like@#erquan%@#
    会使用索引,而
        SELECT * FROM myIndex WHEREt vc_Name like@#%erquan@#
        就不会使用索引了。


    五、索引的不足之处

        上面说了那么多索引的好话,它真的有像传说中那么优秀么?当然会有缺点了。

        1.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件

        2.建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。


        篇尾:
        讲了这么多,无非是想利用索引提高数据库的执行效率。不过索引只是提高效率的一个因素。如果你的MySQL有大数据的表,就需要花时间研究建立最优秀的索引或优化查询语句。

        如果你觉得上面有不妥的地方或有不同的意见或有需要补充的地方,欢迎跟贴讨论^_^。
       
        参考:MYSQL中文手册、MYSQL在线手册、SQLSERVER联机丛书、PC163-IT指南

                            erquan
                            2003/2/25 下午于郑州

     



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1568764

     

    展开全文
  • Java 多线程(一)

    2012-01-12 13:05:13
    1、向服务器上程序都是采用多线程做的,为什么采用多线程呢,就是提高程序运行速度,就说访问数据库吧,服务器可以给每个连接数据库的客户端创建一个线程,然后这个线程就负责这个客户端数据的插入,查询,等操作,...
    1、向服务器上程序都是采用多线程做的,为什么采用多线程呢,就是提高程序运行速度,就说访问数据库吧,服务器可以给每个连接数据库的客户端创建一个线程,然后这个线程就负责这个客户端数据的插入,查询,等操作,每一个客户端访问数据库都会创建一个线程,cpu采用分时操作,所以看起来好象同时多个客户端同时操作数据库一样,提高了访问速度。


    2. Java中的线程由三部分组成
    1. 虚拟的CPU,封装在java.lang.Thread类中。
      2. CPU所执行的代码,传递给Thread类。
      3. CPU所处理的数据,传递给Thread类。
    Java的线程是通过java.lang.Thread类来实现的。当我们生成一个Thread类的对象之后,一个新的线程就产生了。
    它的构造方法:
    public Thread (ThreadGroup group,Runnable target,String name);
    其中,group 指明该线程所属的线程组;target实际执行线程体的目标对象,它必须实现接口Runnable; name为线程名。如果name为null时,则Java自动提供唯一的名称。

    一个类声明实现Runnable接口就可以充当线程体,在接口Runnable中只定义了一个方法 run():
      public void run();
    每个线程都是通过某个特定Thread对象的方法run( )来完成其操作的,方法run( )称为线程体
    1. 创建状态(new Thread)
      执行下列语句时,线程就处于创建状态:
      Thread myThread = new MyThreadClass( );
      当一个线程处于创建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。

      2. 可运行状态( Runnable )
      Thread myThread = new MyThreadClass( );
      myThread.start( );
      当一个线程处于可运行状态时,系统为这个线程分配了它需的系统资源,安排其运行并调用线程运行方法,这样就使得该线程处于可运行( Runnable )状态。需要注意的是这一状态并不是运行中状态(Running ),因为线程也许实际上并未真正运行。由于很多计算机都是单处理器的,所以要在同一时刻运行所有的处于可运行状态的线程是不可能的,Java的运行系统必须实现调度来保证这些线程共享处理器。
      
      3. 不可运行状态(Not Runnable)
      进入不可运行状态的原因有如下几条:
      1) 调用了sleep()方法;
      2) 调用了suspend()方法;
      3) 为等候一个条件变量,线程调用wait()方法;
      4) 输入输出流中发生线程阻塞;
      不可运行状态也称为阻塞状态(Blocked(输入/)。因为某种原因输出、等待消息或其它阻塞情况),系统不能执行线程的状态。这时即使处理器空闲,也不能执行该线程。

      4. 死亡状态(Dead)
      线程的终止一般可通过两种方法实现:自然撤消(线程执行完)或是被停止(调用stop()方法)。目前不推荐通过调用stop()来终止线程的执行,而是让线程执行完。
    class SimpleThread extends Thread {
    public SimpleThread(String str) {
    super(str);
    }
    public void run() {
    for(int i = 0; i < 10; i++) {
    System.out.println(i + " " + getName());
    try {
    sleep((int)(Math.random() * 1000));
    } catch (InterruptedException e) {}
    }

    System.out.println( "DONE! " + getName());
    }
    }
    public class TwoThreadsTest {
    public static void main (String[] args) {
    new SimpleThread( "First ").start();
    new SimpleThread( "Second ").start();
    }

    }
    两个线程是交错运行的,感觉就象是两个线程在同时运行。但是实际上一台计算机通常就只有一个CPU,在某个时刻只能是只有一个线程在运行。
    在编程时要注意给每个线程执行的时间和机会,主要是通过让线程睡眠的办法(调用sleep()方法)来让当前线程暂停执行,然后由其它线程来争夺执行的机会。如果上面的程序中没有用到sleep()方法,则就是第一个线程先执行完毕,然后第二个线程再执行完毕。
    两种方法实现线程体
    1. 定义一个线程类,它继承线程类Thread并重写其中的方法 run()
    2. 提供一个实现接口Runnable的类作为一个线程的目标对象,在初始化一个Thread类或者Thread子类的线程对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体 run()。
    public class Clock extends java.applet.Applet implements Runnable {
    Thread clockThread;
    clockThread = new Thread(this, "Clock ");
    /*线程体是Clock对象本身,线程名字为 "Clock "*/
    clockThread.start(); //启动线程

    3. 构造线程体的两种方法的比较:

      1. 使用Runnable接口
       1) 可以将CPU,代码和数据分开,形成清晰的模型;
       2) 还可以从其他类继承;
       3) 保持程序风格的一致性。

      2. 直接继承Thread类
       1) 不能再从其他类继承;
       2) 编写简单,可以直接操纵线程,无需使用Thread.currentThread()。
    4. 线程的调度
    线程调度器按线程的优先级高低选择高优先级线程(进入运行中状态)执行,同时线程调度是抢先式调度,即如果在当前线程执行过程中,一个更高优先级的线程进入可运行状态,则这个线程立即被调度执行。
    抢先式调度又分为:时间片方式和独占方式。在时间片方式下,当前活动线程执行完当前时间片后,如果有其他处于就绪状态的相同优先级的线程,系统会将执行权交给其他就绪态的同优先级线程;当前活动线程转入等待执行队列,等待下一个时间片的调度。
    在独占方式下,当前活动线程一旦获得执行权,将一直执行下去,直到执行完毕或由于某种原因主动放弃CPU,或者是有一高优先级的线程处于就绪状态。
    下面几种情况下,当前线程会放弃CPU:

      1. 线程调用了yield() 或sleep() 方法主动放弃;

      2. 由于当前线程进行I/O 访问,外存读写,等待用户输入等操作,导致线程阻塞;或者是为等候一个条件变量,以及线程调用wait()方法;

      3. 抢先式系统下,由高优先级的线程参与调度;时间片方式下,当前时间片用完,由同优先级的线程参与调度
    线程的优先级
    线程的优先级用数字来表示,范围从1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一个线程的缺省优先级是5,即Thread.NORM_PRIORITY
    int getPriority(); //得到线程的优先级
      void setPriority(int newPriority);
      //当线程被创建后,可通过此方法改变线程的优先级
    一个线程在空闲时应该主动放弃CPU,以使其他同优先级和低优先级的线程得到执行
    public class ThreadTest{
    public static void main (String[] args) {
    Thread t1 = new MyThread( "T1 ");
    t1.setPriority( Thread.MIN_PRIORITY );
    t1.start( );
    Thread t2 = new MyThread( "T2 ");
    t2.setPriority( Thread.MAX_PRIORITY );
    t2.start( );
    Thread t3 = new MyThread( "T3 ");
    t3.setPriority( Thread.MAX_PRIORITY );
    t3.start( );
    }
    }
    class MyThread extends Thread {
    String message;
    MyThread (String message) {
    this.message = message;
    }
    public void run() {
    for ( int i=0; i <3; i++ )
    System.out.println( message+ " "+getPriority() );
    }
    }

    1.终止线程

      线程终止后,其生命周期结束了,即进入死亡态,终止后的线程不能再被调度执行,以下几种情况,线程进入终止状态:
      1) 线程执行完其run()方法后,会自然终止。
      2) 通过调用线程的实例方法stop()来终止线程。
    2. 测试线程状态

      可以通过Thread 中的isAlive() 方法来获取线程是否处于活动状态;线程由start() 方法启动后,直到其被终止之间的任何时刻,都处于 'Alive '状态。

     3. 线程的暂停和恢复

      有几种方法可以暂停一个线程的执行,在适当的时候再恢复其执行。
      1) sleep() 方法
      当前线程睡眠(停止执行)若干毫秒,线程由运行中状态进入不可运行状态,停止执行时间到后线程进入可运行状态。

      2) suspend()和resume()方法
      线程的暂停和恢复,通过调用线程的suspend()方法使线程暂时由可运行态切换到不可运行态,若此线程想再回到可运行态,必须由其他线程调用resume()方法来实现。
      注:从JDK1.2开始就不再使用suspend()和resume()。

      3) join()
      当前线程等待调用该方法的线程结束后, 再恢复执行.
      TimerThread tt=new TimerThread(100);
      tt.start();
      …
      public void timeout(){
      tt.join();// 当前线程等待线程tt 执行完后再继续往下执行
      … }


    临界资源问题

      前面所提到的线程都是独立的,而且异步执行,也就是说每个线程都包含了运行时所需要的数据或方法,而不需要外部的资源或方法,也不必关心其它线程的状态或行为。但是经常有一些同时运行的线程需要共享数据,此时就需考虑其他线程的状态和行为,否则就不能保证程序的运行结果的正确性

    为解决操作的不完整性问题,在Java 语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为 " 互斥锁 " 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。
    互斥锁
    class stack{
        public void push(char c){
        synchronized(this){ //this表示Stack的当前对象
          data[idx]=c;
          idx++;
         }
        }
        public char pop(){
          synchronized(this){ //this表示Stack的当前对象
          idx--;
          return data[idx];
          }
        }
    }
      synchronized 除了象上面讲的放在对象前面限制一段代码的执行外,还可以放在方法声明中,表示整个方法为同步方法。
      public synchronized void push(char c){
      …
        }

      如果synchronized用在类声明中,则表明该类中的所有方法都是synchronized的。
    多线程的同步
     class SyncStack{ //同步堆栈类
       private int index = 0; //堆栈指针初始值为0
       private char []buffer = new char[6]; //堆栈有6个字符的空间

       public synchronized void push(char c){ //加上互斥锁
         while(index = = buffer.length){ //堆栈已满,不能压栈
         try{
            this.wait(); //等待,直到有数据出栈
           }catch(InterruptedException e){}
           }
       this.notify(); //通知其它线程把数据出栈
       buffer[index] = c; //数据入栈
       index++; //指针向上移动
       }
       public synchronized char pop(){ //加上互斥锁
           while(index ==0){ //堆栈无数据,不能出栈
            try{
               this.wait(); //等待其它线程把数据入栈
            }catch(InterruptedException e){}
              }
           this.notify(); //通知其它线程入栈
           index- -; //指针向下移动
           return buffer[index]; //数据出栈
        }
           }
        class Producer implements Runnable{ //生产者类
           SyncStack theStack;
            //生产者类生成的字母都保存到同步堆栈中

           public Producer(SyncStack s){
              theStack = s;
           }
           public void run(){
              char c;
              for(int i=0; i <20; i++){
                c =(char)(Math.random()*26+ 'A ');
                              //随机产生20个字符
                theStack.push(c); //把字符入栈
                System.out.println( "Produced: "+c); //打印字符
                try{
                Thread.sleep((int)(Math.random()*1000));
                         /*每产生一个字符线程就睡眠*/
                }catch(InterruptedException e){}
              }
           }
         }
         class Consumer implements Runnable{ //消费者类
             SyncStack theStack;
                      //消费者类获得的字符都来自同步堆栈

             public Consumer(SyncStack s){
                 theStack = s;
             }
             public void run(){
                 char c;
                 for(int i=0;i <20;i++){
                   c = theStack.pop(); //从堆栈中读取字符
                 System.out.println( "Consumed: "+c);
                                 //打印字符
                 try{
                 Thread.sleep((int)(Math.random()*1000));
                        /*每读取一个字符线程就睡眠*/
                 }catch(InterruptedException e){}
             }
           }
         }
         public class SyncTest{
           public static void main(String args[]){
             SyncStack stack = new SyncStack();
       //下面的消费者类对象和生产者类对象所操作的是同一个同步堆栈对象
             Runnable source=new Producer(stack);
             Runnable sink = new Consumer(stack);
             Thread t1 = new Thread(source); //线程实例化
             Thread t2 = new Thread(sink); //线程实例化
             t1.start(); //线程启动
             t2.start(); //线程启动
           }
         }
    通过运用wait()和notify()方法来实现线程的同步,在同步中还会用到notifyAll()方法
    (1) wait,nofity,notifyAll必须在已经持有锁的情况下执行,所以它们只能出现在synchronized作用的范围内,也就是出现在用synchronized修饰的方法或类中。

      (2) wait的作用:释放已持有的锁,进入等待队列.
      
      (3) notify的作用:唤醒wait队列中的第一个线程并把它移入锁申请队列.

      (4) notifyAll的作用:唤醒wait队列中的所有的线程并把它们移入锁申请队列.

    堵塞
    (1) 调用sleep(毫秒数),使线程进入“睡眠”状态。在规定的时间内,这个线程是不会运行的。
    (2) 用suspend()暂停了线程的执行。除非线程收到resume()消息,否则不会返回“可运行”状态。
    (3) 用wait()暂停了线程的执行。除非线程收到nofify()或者notifyAll()消息,否则不会变成“可运行”(是的,这看起来同原因2非常相象,但有一个明显的区别是我们马上要揭示的)。
    (4) 线程正在等候一些IO(输入输出)操作完成。
    (5) 线程试图调用另一个对象的“同步”方法,但那个对象处于锁定状态,暂时无法使用。
    展开全文
  • ASP.NET使用多线程

    千次阅读 2012-01-14 17:58:52
     使用多线程是为了提高CPU的利用率,即在在相同的时间里面做更多的事情(但前提是系统资源没有完全耗尽),ASP.NET中使用多线程可以加快页面在服务器端的生成速度。一般页面生成过程中花费时间最多的是数据库查询...
    Web开发中使用多线程可以增强用户体验,尤其是多用户、多任务、海量数据和资源紧张的情况下。下面这些代码范例都是入门级的,希望对对大家学习ASP.Net多线程编程有所帮助。
    

      使用多线程是为了提高CPU的利用率,即在在相同的时间里面做更多的事情(但前提是系统资源没有完全耗尽),ASP.NET中使用多线程可以加快页面在服务器端的生成速度。一般页面生成过程中花费时间最多的是数据库查询阶段,如果你的页面有10个查询,不使用多线程的话,这10个查询将是串行执行的——即依次执行每一个查询。如果使用多线程,将可以使这10个查询几乎同时执行。这显然会提高页面的生成速度。

      在网上搜索了些许帖子说在IIS进程中使用多线程是不稳定的,可我经过实践却发现ASP.NET使用多线程也没出啥问题。不过在ASP.NET中使用多线程得注意一些地方,不然确实是不稳定,甚至是行不通的。比如不能在多线程中使用HttpContext下的任何方法和属性,这就包括Cookie、Session、Response、Request、Application等等,当使用这些方法或者属性的时候,IIS进程将会直接崩溃。更要注意的是,由于多线程与页面的加载(Load)是异步执行的,必须让这些创建的线程在Load执行完之前同步,不然可能导致数据没有加载成功。 可能会有人问HttpContext等都被限制了,页面中还能做什么呢?我们完全可以把创建的线程与页面主体隔开,把需要的数据先在页面主体中获取,然后直接传入到创建的线程中就可解决。话不多说,具体如何,请看下文。

      假设某个页面中有2个SQL查询,一个是根据Url传递来的参数P确定当前页的内容,另一个查询是显示所有分类。第一个查询语句需要用到Request.QueryString获取P传递来的页码,第二个查询语句则可直接写SQL语句。

      假设第一个查询语句如:SELECT * FROM Archives WHERE Page=传递的页码

      假设第二个查询语句如:SELECT * FROM Category

      我们先创建一个类,用于接受参数P和数据绑定控件ID(此处使用Repeater控件绑定数据),此类能够把SQL语句查询的结果绑定到数据控件(Repeater)中。

      public classBindData

      {

      private int currentPage = 1;

      private Repeater rpID;

      public BindData(Repeater rpID)

      {

      this.rpID = rpID;

      }

      public BindData(Repeater rpID,int page)

      {

      this.rpID = rpID;

      this.currentPage = page;

      }

      public void BindCategory()

      {

      string strSql="SELECT * FROM Category";

      this.BindDataToRepeater(strSql, this.rpID);

      }

      public void BindArchive()

      {

      string strSql = string.Format("SELECT * FROM Archives WHERE Page={0}",this.currentPage);

      this.BindDataToRepeater(strSql, this.rpID);

      }

      private void BindDataToRepeater(string strSql, Repeater rp)

      {

      if (rp == null) return;

      SqlConnection conn = new SqlConnection("data source=数据服务器地址;User ID=用户名;pwd=密码;Initial Catalog=数据库名");


      SqlCommand cmd = new SqlCommand(strSql, conn);

      SqlDataReader dtr;

      try

      {

      conn.Open();

      dtr = cmd.ExecuteReader();

      controlID.DataSource = rp;

      controlID.DataBind();

      if (!dtr.IsClosed)

      dtr.Close();

      }

      catch { }

      finally

      {

      cmd.Dispose();

      if (conn.State = ConnectionState.Open)

      conn.Close();

      }

      }

      }
      上面创建的BindData类中有2个构造函数,分别用于绑定分类、绑定Arhive的不同形式。如果使用其他数据绑定控件则可进行相应修改;

      创建了1个私有方法BindDataToRepeater用于把对应的SQL语句查询的结果绑定到对应的Repeater控件上。同时在此方法中使用了SqlDataReader,以提高绑定数据的速度。如果你使用了数据工厂可修改BindDataToRepeater中的具体实现过程;

      2个共有方法BindCategory和BindArchive分别用于创建不同SQL语句、设置Repater的ID;

      同时需要引入System.Web.UI、System.Web.UI.HtmlControls、System.Data.SqlClient3个必要的命名空间。

      值得注意的是在BindDataToRepeater方法中使用了try..catch语句,但并没有在catch块中做任何事情,为什么我们用try.catch却不在catch块中做点什么事情呢,不是多此一举吗?使用try..catch是为了防止在执行BindDataToRepeater时抛出异常,若此处出现异常且此方法是在多线程中执行的,将会导致IIS进程崩溃,进而影响其他页面的正常执行,故而用try...catch防止BindDataToRepeater抛出错误。

      我们之所以为数据绑定创建一个类,是为了提高内存利用率,当数据加载(Load)完毕的时候,为这个类创建的实例就会销毁。我们也可以通过在页面中创建几个全局变量来实现。但我还是建议以类的形式传递数据而不是使用全局变量。下面,我们开始在页面的Load中创建线程了。首先你需要在页面中引入System.Threading命名空间。

      public classBindData

      {

      private int currentPage = 1;

      private Repeater rpID;

      public BindData(Repeater rpID)

      {

      this.rpID = rpID;

      }

      public BindData(Repeater rpID,int page)

      {

      this.rpID = rpID;

      this.currentPage = page;

      }

      public void BindCategory()

      {

      string strSql="SELECT * FROM Category";

      this.BindDataToRepeater(strSql, this.rpID);

      }

      public void BindArchive()

      {

      string strSql = string.Format("SELECT * FROM Archives WHERE Page={0}",this.currentPage);

      this.BindDataToRepeater(strSql, this.rpID);

      }

      private void BindDataToRepeater(string strSql, Repeater rp)

      {

      if (rp == null) return;

      SqlConnection conn = new SqlConnection("data source=数据服务器地址;User ID=用户名;pwd=密码;Initial Catalog=数据库名");

      SqlCommand cmd = new SqlCommand(strSql, conn);

      SqlDataReader dtr;

      try


     {

      conn.Open();

      dtr = cmd.ExecuteReader();

      controlID.DataSource = rp;

      controlID.DataBind();

      if (!dtr.IsClosed)

      dtr.Close();

      }

      catch { }

      finally

      {

      cmd.Dispose();

      if (conn.State = ConnectionState.Open)

      conn.Close();

      }

      }

      }

      上面的代码显示在!IsPostBack状态下绑定数据。利用Request.QueryString获取了当前页码,并创建了BindData的2个实例LoadArchives、LoadCategory,通过 Thread thArhives=new Thread(new ThreadStart(LoadArchives.BindArchive))为绑定Arhice创建线程,通过Thread thCategory = new Thread(new ThreadStart(LoadCategory.BindCategory))为绑定分类创建线程,同时调用Thread的Start方法使2个线程进入执行状态。最后,在Load的最下面用Thread的Join方法使创建的2个线程与页面加载同步。

      值得注意的是,Join方法是必须的,如果不使用,可能导致创建的线程还未把数据完全绑定到Repeater上,Load就已经执行完毕,若如此页面上将没有任何数据。同时调用Start的代码行应尽量早,调用Join的代码行都应尽量迟——尽量放在Page_Load代码段的末尾,这样才能达到多线程的目的,若你每调用一个Start马上调用Join,其实质和没有使用多线程的效果是一样的。Join在MSND上的解释是:在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。

      只要设置好ASPX页面Repeater的绑定项,数据就可成功加载了。上面仅仅展示了2个SQL语句的查询,如果你有10个或者更多的SQL查询,在Page_Load中创建10个线程,让他们异步执行,最后用Join同步到Load,是一个提高性能的不错方法。
    展开全文
  • ​ 工作中,如果数据库存储数据量过大、信息过多时,往往数据库的执行速度会降低,也就是查询或者删除的操作缓慢(或者迟迟不响应,甚至系统崩溃掉~~),这时,你或许会去调整内存、缓存大小来优化数据库性能。...
  • mysql数据库

    2015-12-05 11:17:19
    MySQL是一个多线程的,结构化查询语言(SQL)数据库服务器。SQL 在世界上是最流行的数据库语言。MySQL 的执行性能非常高,运行速度非常快,并非常容易使用。是一个非常棒的数据库。新的版本可以作为复杂情况以及大负荷...
  • MySQL数据库有哪些特点

    千次阅读 2019-03-19 09:17:00
     它是C和C++语言编写的、支持多个操作系统、支持多线程、为多种编程语言提供API、优化SQL算法提高查询速度以及提供用于管理和检查数据库的管理工具 MySQL数据库  MySQL是一种关系型数据库管理系统,它将数据...
  • 提高 Activity 跳转速度

    2020-08-25 19:36:29
    从一个页面跳转到另外一个页面,这在 Android 中是...第一类就是看看是否在UI线程左耗时操作,这个经常是数据方面的问题,比如说要从数据库里面查询数据,或者说对数据做了一些复杂逻辑的操作,例如要对集合中的数据,
  • 一.Mysql数据库 MySQL是一种关系数据库管理系统,关系数据库...优化的 SQL查询算法,有效地提高查询速度,既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中。Lin...
  • 优化SQL查询算法,有效提高查询速度 提供语言支持,常见的编码如GB2312、UTF-8 提供TCP/IP、 ODBC和JDBC等多种数据库连接途径 提供用于管理数据库操作的管理工具 支持多种存储引擎,并且采用了GPL协议,你可以修改...
  • 主机日志传输到备机时,备机日志落盘的同时,发送给重做恢复分发线程,分发线程根据日志类型和日志操作的数据页发给个并行恢复线程进行日志重做,保证备机的重做速度跟上主机日志的产生速度。这样备机实时处于...
  • 一.Mysql数据库 MySQL是一种关系数据库管理系统,关系数据库将...优化的 SQL查询算法,有效地提高查询速度,既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中。...
  • 关系数据库将数据保存在不同的表中而不是将所有数据放在一个大仓库内,能够增加查询效率提高灵活性,优点:体积小、查询速度快、支持多种操作系统总体拥有成本低、支持多线程能充分利用CPU。 - Redis 是一个开源的...
  • MySQL 是最流行的关系型数据库管理系统(RDBMS)之一,MySQL优化了SQL查询算法,有效地提高查询速度;支持多线程,充分利用CPU资源,支持多用户;提供用于管理、检查、优化数据库操作的管理工具。由于其体积小、速度快...
  • # MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大 sort_buffer_size = ...
  • 由于内存数据库具有比基于磁盘的数据库更高的查询响应速度和并发度,其被广泛应用于银行、证券交易所和在线购物等数据量庞大并且实时性要求高的商业领域。索引能够有效降低数据的搜索空间、提高内存数据库查询效率...
  • 为了提高处理速度,采用了多线程。 同时,为了防止任务处理完方法就走到最后了,使用了CountDownLatch。 核心代码如下 List<OperatorProcessVO> vos = Collections.synchronizedList(new ArrayList<>())...
  • 发现,相比于每次从数据库查询数据,程序执行速度提高了很多。 今天,我决定对这个需求继续优化。采用多线程的方式来实现。 先来看一下优化之前的代码: long startTime = System.currentTimeMillis(); model....
  • java简单搭建分布式架构

    万次阅读 2018-03-20 20:28:50
    一般来说,数据库的数据过多,查询效率就很慢,这时候我们如果把表分库到不同的数据库,这时候访问速度就会快很多,如果并且采用多线程去访问的话,查询速度也会提高的更快,我这里是运行内存8核电脑进行测试的单个...
  • 调整bulk_insert_buffer_size变量也能提高(向包含行的表格中)插入的速度。  3)可以对myisam表并行插入Concurrent_insert系统变量可以被设置用于修改concurrent-insert处理。该变量默认设置为1。如果concurrent_...
  • MYSQL 5.7.12.zip

    2019-07-11 11:20:07
    优化的SQL查询算法,有效地提高查询速度 6.既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中。 7.提供语言支持,常见的编码如中文的GB 2312、BIG5,...
  • 今天学了下多线程中超时任务的处理,这里...这种情况下处理的都是比较耗时的操作,比如请求资源,数据库查询等,当超过一定时间没有返回结果,就结束线程,提高响应速度。 具体步骤如下: 实现Runnable接口或者...
  • Linux mysql-5.7.12

    2018-12-12 01:35:06
    5.优化的SQL查询算法,有效地提高查询速度 6.既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中。 7.提供语言支持,常见的编码如中文的GB 2312、BIG5,日文的...
  • redis是一款高性能key-value(键值对)内存型数据库,是非关系型数据库的一种,它采用单线程的架构方式,避免了多线程存在的锁处理造成的资源耗费,读取速度非常快,非常适合变化不是太大但数据量很大的数据的存储和...
  • 3.MySQL使用标准的SQL数据语言形式,支持多线程,充分利用CPU资源优化的SQL查询算法,有效的提高查询速度 应用场景:Web网站系统 Mongodb 1.面向集合的存储:适合存储JSON风格文件的形式 2.模式自由:可以把不同结构...
  • Mysql,Mongodb,Redis对比

    2020-04-08 23:50:38
    3.MySQL使用标准的SQL数据语言形式,支持多线程,充分利用CPU资源优化的SQL查询算法,有效的提高查询速度 应用场景:Web网站系统 Redis 1.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启...
  • 今天学了下多线程中超时任务的处理,这里和...这种情况下处理的都是比较耗时的操作,比如请求资源,数据库查询等,当超过一定时间没有返回结果,就结束线程,提高响应速度。 具体步骤如下: 实现Runnable接口或...

空空如也

空空如也

1 2 3 4 5 6
收藏数 114
精华内容 45
关键字:

多线程数据库提高查询速度