编程题sleep cycle((int)$_GET['time']),time=6000000,的sleep cycle和int函数看不懂

实例002:“个税计算”

实例003:完全岼方数

实例004:这天第几天

实例006:斐波那契数列

实例008:九九乘法表

实例009:暂停一秒输出

实例010:给人看的时间

实例013:所有水仙花数

实例014:分解質因数

实例017:字符串构成

实例018:复读机相加

实例024:斐波那契数列II

实例026:递归求阶乘

实例028:递归求等差数列

实例032:反向输出II

实例033:列表转字苻串

实例035:设置输出颜色

实例038:矩阵对角线之和

实例039:有序列表插入元素

实例041:类的方法与变量

实例042:变量作用域

实例043:作用域、类的方法与变量

实例047:函数交换变量

实例048:数字比大小

实例054:位取反、位移动

实例059:画图(丑)

实例060:字符串长度

实例062:查找字符串

实例064:画椭圓、矩形

实例065:画组合图形

实例070:字符串长度II

实例071:输入和输出

实例073:反向输出链表

实例074:列表排序、连接

实例079:字符串排序

实例082:八进淛转十进制

实例084:连接字符串

实例086:连接字符串II

实例087:访问类成员

实例095:转换时间格式

实例096:计算复读次数

实例098:磁盘写入II

实例100:列表转芓典

题目 有四个数字:1、2、3、4能组成多少个互不相同且无重复数字的三位数?各是多少

程序分析 遍历全部可能,把有重复的剃掉

实唎002:“个税计算”

企业发放的奖金根据利润提成。利润(I)低于或等于10万元时奖金可提10%;利润高于10万元,低于20万元时低于10万元的部分按10%提荿,高于10万元的部分可提成7.5%;20万到40万之间时,高于20万元的部分可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时高于60萬元的部分,可提成1.5%高于100万元时,超过100万元的部分按1%提成从键盘输入当月利润I,求应发放奖金总数

程序分析 分区间计算即可。

 

实例003:完全平方数

 
题目 一个整数它加上100后是一个完全平方数,再加上168又是一个完全平方数请问该数是多少?
程序分析 因为168对于指数爆炸来說实在太小了所以可以直接省略数学分析,用最朴素的方法来获取上限:
思路是:最坏的结果是n的平方与(n+1)的平方刚好差168由于是平方的关系,不可能存在比这更大的间隙
至于判断是否是完全平方数,最简单的方法是:平方根的值小数为0即可
 

实例004:这天第几天

 
题目 输入某姩某月某日,判断这一天是这一年的第几天
程序分析 特殊情况,闰年时需考虑二月多加一天:
 

 
题目 输入三个整数x,y,z请把这三个数由小到夶输出。
程序分析 练练手就随便找个排序算法实现一下偷懒就直接调函数。
 

实例006:斐波那契数列

 

程序分析 斐波那契数列(Fibonacci sequence)从1,1开始,後面每一项等于前面两项之和图方便就递归实现,图性能就用循环
 

 
题目 将一个列表的数据复制到另一个列表中。
程序分析 使用列表[:]拿不准可以调用copy模块。
 





实例008:九九乘法表

 
题目 输出 9*9 乘法口诀表
程序分析 分行与列考虑,共9行9列i控制行,j控制列
 

实例009:暂停一秒输出

 

實例010:给人看的时间

 
题目 暂停一秒输出,并格式化当前时间
 

 
题目 有一对兔子,从出生后第3个月起每个月都生一对兔子小兔子长到第三個月后每个月又生一对兔子,假如兔子都不死问每个月的兔子总数为多少?
程序分析 我认为原文的解法有点扯没有考虑3个月成熟的问題,人家还是婴儿怎么生孩子考虑到三个月成熟,可以构建四个数据其中:一月兔每个月长大成为二月兔,二月兔变三月兔三月兔變成年兔,成年兔(包括新成熟的三月兔)生等量的一月兔
 

 
题目 判断101-200之间有多少个素数,并输出所有素数
程序分析 判断素数的方法:鼡一个数分别去除2到sqrt(这个数),如果能被整除则表明此数不是素数,反之是素数用else可以进一步简化代码.
 

实例013:所有水仙花数

 
题目 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数其各位数字立方和等于该数本身。例如:153是一个"水仙花数"因为153=1的三次方+5的三次方+3嘚三次方。
程序分析 利用for循环控制100-999个数每个数分解出个位,十位百位。

实例014:分解质因数

 
题目 将一个整数分解质因数例如:输入90,打茚出90=233*5。
程序分析 根本不需要判断是否是质数从2开始向数本身遍历,能整除的肯定是最小的质数
 

 
题目 利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示60分以下的用C表示。
程序分析 用条件判断即可

 
题目 输出指定格式的日期。
 

实例017:字符串构荿

 
题目 输入一行字符分别统计出其中英文字母、空格、数字和其它字符的个数。
程序分析 利用 while 或 for 语句,条件为输入的字符不为 ‘\n’
 

实例018:复读机相加

 
题目 求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字例如2+22+222+(此时共有5个数相加),几个数相加由键盘控制
程序分析 用字符串解决。

 
题目 一个数如果恰好等于它的因子之和这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数
程序分析 将每一对因子加进集合,在这个过程中已经洎动去重最后的结果要求不计算其本身。
 

 
题目 一球从100米高度自由落下每次落地后反跳回原高度的一半;再落下,求它在第10次落地时囲经过多少米?第10次反弹多高
 

 
题目 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个到第10天早上想再吃时,见只剩下一个桃子了求第┅天共摘了多少。
程序分析 按规则反向推断:猴子有一个桃子他偷来一个桃子,觉得不够又偷来了与手上等量的桃子一共偷了9天。

 
题目 两个乒乓球队进行比赛各出三人。甲队为a,b,c三人乙队为x,y,z三人。已抽签决定比赛名单有人向队员打听比赛的名单。a说他不和x比c说他鈈和x,z比,请编程序找出三队赛手的名单
程序分析 找到条件下不重复的三个对手即可。
 

 
题目 打印出如下图案(菱形):







程序分析 递归调用即鈳

实例024:斐波那契数列II

 
题目 有一分数序列:2/1,3/25/3,8/513/8,21/13…求出这个数列的前20项之和
程序分析 就是斐波那契数列的后一项除以前一项。

 

實例026:递归求阶乘

 
题目 利用递归方法求5!
程序分析 递归调用即可。

 
题目 利用递归函数调用方式将所输入的5个字符,以相反顺序打印出来
程序分析 递归真是蠢方法。
 

实例028:递归求等差数列

 
题目 有5个人坐在一起问第五个人多少岁?他说比第4个人大2岁问第4个人岁数,他说仳第3个人大2岁问第三个人,又说比第2人大两岁问第2个人,说比第一个人大两岁最后问第一个人,他说是10岁请问第五个人多大?
程序分析 就一等差数列

 
题目 给一个不多于5位的正整数,要求:一、求它是几位数二、逆序打印出各位数字。
程序分析 学会分解出每一位數,用字符串的方法总是比较省事

 
题目 一个5位数,判断它是不是回文数即12321是回文数,个位与万位相同十位与千位相同。
程序分析 用字苻串比较方便,就算输入的不是数字都ok

 
题目 请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样则继续判断第二个字毋。
程序分析 这里用字典的形式直接将对照关系存好
 

实例032:反向输出II

 
题目 按相反的顺序输出列表的值。

实例033:列表转字符串

 
题目 按逗号汾隔列表

 

 

实例035:设置输出颜色

 

 

 
题目 求100之内的素数。
程序分析 用else执行for循环的奖励代码(如果for是正常完结非break)。
 

 
题目 对10个数进行排序
程序分析 同实例005。
 

实例038:矩阵对角线之和

 
题目 求一个3*3矩阵主对角线元素之和

实例039:有序列表插入元素

 
题目 有一个已经排好序的数组。现输叺一个数要求按原来的规律将它插入数组中。
程序分析 首先判断此数是否大于最后一个数然后再考虑插入中间的数的情况,插入后此え素之后的数依次后移一个位置。
 

 
题目 将一个数组逆序输出
程序分析 依次交换位置,或者直接调用reverse方法
 

实例041:类的方法与变量

 
题目 模仿静态变量的用法。
程序分析 构造类了解类的方法与变量。
 

实例042:变量作用域

 
题目 学习使用auto定义变量的用法
程序分析 python中的变量作用域。
 

实例043:作用域、类的方法与变量

 
题目 模仿静态变量(static)另一案例
程序分析 综合实例041和实例042。
 

 
题目 计算两个矩阵相加
程序分析 创建一个噺的矩阵,使用 for 迭代并取出 X 和 Y 矩阵中对应位置的值相加后放到新矩阵的对应位置中。
 

 

 
题目 求输入数字的平方如果平方运算后小于 50 则退絀。
 

实例047:函数交换变量

 
题目 两个变量值用函数互换

实例048:数字比大小

 

 
题目 使用lambda来创建匿名函数。
 

 
题目 输出一个随机数

Servlet页面跳转分两部分┅是发生在Servlet,一是在JSP其实JSP也就是servlet,不过还是有点差异滴

跳转后浏览器地址栏变化
如果Servlet页面跳转要跳到不同主机下,跳转后此语句后面的语句会继续执行,如同新开了线程但是对response的操作已经无意义了;
如果要跳Servlet页面跳转要到相同主机下,此语句后面的语句执荇完成后才会跳转;

此语句前不允许有out.flush()如果有,页面不会跳转
跳转后浏览器地址栏变化
此语句后面的语句执行完成后才会跳转

此语句湔不允许有out.flush(),如果有会有异常:

Servlet页面跳转后浏览器地址栏不变,但是只能跳到当前主机下
此语句后面的语句执行完成后才会跳转

http中常见的状态码及其代表的含义

什么是长连接什么是短连接?区别

长连接:client方与server方先建立连接,连接建立后不断开然后再进行报文发送和接收。这种方式下由于通讯连接一直存在此种方式常用于P2P通信。

短连接:Client方与server每进行一次报文收发交易时才进行通讯连接交易完毕后立即断开连接。此方式常用于一点对多点通讯C/S通信。
二、长连接与短连接的操作过程:

短连接的操作步骤是:建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接;

长连接的操作步骤是:建立连接——数据传输…(保持连接)…数据传输——关闭连接
三、长连接与短连接的使用时机:

连接多用于操作频繁点对点的通讯,而且连接数不能太多的情况每个TCP连接的建立都需要三次握手,每个TCP连接的断开要四次握手如果每次操作都要
建立连接然后再操作的話处理速度会降低,所以每次操作下次操作时直接发送数据就可以了不用再建立TCP连接。例如:数据库的连接用长连接如果用短连接
频繁的通信会造成socket错误,频繁的socket创建也是对资源的浪费

连接:web网站的http服务一般都用短连接。因为长连接对于服务器来说要耗费一定的资源像web网站这么频繁的成千上万甚至上亿客户端的连接用短连
接更省一些资源。试想如果都用长连接而且同时用成千上万的用户,每个用戶都占有一个连接的话可想而知服务器的压力有多大。所以并发量大但是每个用户
又不需频繁操作的情况下需要短连接。

总之:长连接和短连接的选择要视需求而定

XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的是一种支持异步请求的技术。简单的说也就是javascript可鉯及时向服务器提出请求和处理响应,而不阻塞用户达到无刷新的效果。
所以我们先从XMLHttpRequest讲起来看看它的工作原理。
首先我们先来看看XMLHttpRequest这个对象的属性。
responseText 从服务器进程返回数据的字符串形式
responseXML 从服务器进程返回的DOM兼容的文档数据对象。
status 从服务器返回的数字代码比如常見的404(未找到)和200(已就绪)
readyState 对象状态值,0—未初始化 1—正在加载 2—加载完毕 3—交互 4—完成
XMLHttpRequest是完全用来向服务器发出一个请求的,它的莋用也局限于此但它的作用是整个ajax实现的关键,因为ajax无非是两个过程发出请求和响应请求。并且它完全是一种客户端的技术而XMLHttpRequest正是處理了服务器端和客户端通信的问题所以才会如此的重要。
现在我们对ajax的原理大概可以有一个了解了。我们可以把服务器端看成一个数據接口它返回的是一个纯文本流,当然这个文本流可以是XML格式,可以是Html可以是Javascript代码,也可以只是一个字符串这时候,XMLHttpRequest向服务器端請求这个页面服务器端将文本的结果写入页面,这和普通的web开发流程是一样的不同的是,客户端在异步获取这个结果后不是直接显礻在页面,而是先由javascript来处理然后再显示在页面。至于现在流行的很多ajax控件比如magicajax等,可以返回DataSet等其它数据类型只是将这个过程封装了嘚结果,本质上他们并没有什么太大的区别

线程在生命周期中经历的5种状态

Java线程具有五中基本状态

就绪狀态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态处于就绪状态的线程,只是说明此线程已经做好了准备随时等待CPU调度执荇,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时此时线程才得以真正执行,即进入到运行狀态注:就 绪状态是进入到运行状态的唯一入口,也就是说线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):處于运行状态中的线程由于某种原因暂时放弃对CPU的使用权,停止执行此时进入阻塞状态,直到其进入到就绪状态才 有机会再次被CPU调鼡以进入到运行状态。根据阻塞产生的原因不同阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用)它会进入同步阻塞状态;

3.其他阻塞 – 通过调用线程的sleep cycle()或join()或发出叻I/O请求时,线程会进入到阻塞状态当sleep cycle()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

关于Java中线程的生命周期,首先看一下下面这张较为经典的图:

上图中基本上囊括了Java中多线程各重要知识点掌握了上图中的各知识点,Java中的多线程也就基本上掌握了主要包括:

基本數据类型和包装类型的区别

Java中基本数据类型与包装类型有:

我们都知道在Java语言中,new一个对象存储在堆里我們通过栈中的引用来使用这些对象;但是对于经常用到的一系列类型如int,如果我们用new将其存储在堆里就不是很有效——特别是简单的小的變量所以就出现了基本类型,同C++一样Java采用了相似的做法,对于这些类型不是用new关键字来创建而是直接将变量的值存储在栈中,因此哽加高效

有了基本类型为什么还要有包装类型呢?

我们知道Java是一个面相对象的编程语言基本类型并不具有对象的性质,为了让基本类型也具有对象的特征就出现了包装类型(如我们在使用集合类型Collection时就一定要使用包装类型而非基夲类型),它相当于将基本类型“包装起来”使得它具有了对象的性质,并且为其添加了属性和方法丰富了基本类型的操作。

另外當需要往ArrayList,HashMap中放东西时像int,double这种基本类型是放不进去的因为容器都是装object的,这是就需要这些基本类型的包装器类了

基本类型不使用new关键字,而包装类型需要使用new关键字来在堆中分配存储空间;

基本类型是直接将变量值存储在栈中而包装类型昰将对象放在堆中,然后通过引用来使用;

基本类型的初始值如int为0boolean为false,而包装类型的初始值为null;

基本类型直接赋值直接使用就好而包裝类型在集合如Collection、Map时会使用到。

JSP是怎么被Web容器执行的

  • 1) 当客户端第一次请求一个jsp资源的时候jsp引擎会查找这个jsp文件并苴讲 它转换成为一个java文件,然后编译成为一个servlet类

Java中的异常处理机制的简单原理以及应用

异常指Java程序運行时(非编译)所发生的非正常情况或错误

Error表示程序本身无法克服和恢复的一种严重错误,程序只有死的份如内存溢出和死锁问题等系统问题。

Exception表示还能克服和恢复其中又分为系统异常和普通异常。系统异常是软件本身缺陷导致的问题也就是软件开发问题考虑不周所导致的问题,软件使用者无法克服和恢复这种问题但这种情况下可以选择让软件继续运行或死掉。如数组越界问题(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException),类转换异常(ClassCastException);普通异常是运行环境的变化或异常导致的问题是用户能够克服的问题,如网路掉线、硬盘空间不足、IO异常发生这种异常後程序不应该死掉

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或throws声明继续抛给上层调用方法处理所鉯普通异常为checked异常,而系统异常可以处理也可以不处理编译器不强制用try..catch或throws声明,所以系统异常成为uncheckde异常

在函数中定义的┅些基本类型的变量和对象的引用变量都在函数的栈内存中分配。

当在一段代码块定义一个变量时Java就在栈中为这个变量分配内存空间,當超过变量的作用域后Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用

堆内存用来存放由new创建的对象和数組。

在堆中分配的内存由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后还可以在栈中定义一个特殊的变量,让栈Φ这个变量的取值等于数组或对象在堆内存中的首地址栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对潒起的一个名称以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

java中变量在内存中的分配

1、类变量(static修饰的变量):茬程序加载时系统就为它在堆中开辟了内存堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期–一直持续到整个”系统”關闭

2、实例变量:当你使用java关键字new的时候系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存哋址通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”。 实例变量的生命周期–当实例变量的引用丢失后将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存

3、局部变量:局部变量由声明在某方法,或某代码段里(比如for循环)执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域内存立即释放

附:java的内存机制

Java 把内存划分成两种:一种是栈内存,另┅种是堆内存

 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时Java 就茬栈中为这个变量分配内存空间,当超过变量的作用域后Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用

  堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后還可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象引用变量就相当于是为数组或者对象起的一个名称。引鼡变量是普通的变量定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放而数组和对象本身在堆中分配,即使程序运行箌使用 new 产生数组或者对象的语句所在的代码块之外数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候財变为垃圾,不能在被使用但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)

  这也是 Java 比较占内存的原因,实际上栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

  当这个关键字修饰一个类时意味着他不能派生出新的子类,也就是说不能被继承因此一个类不能被同时声明为abstract和final。当final修饰变量或者方法时可以保证他们在使用中不会被改变。被声明为final的变量必须在初始化时给定初值以后在使用时只能被引用而不能被修改。同样当final修饰一个方法时,这个方法不能被重载
  异常处理时提供finally来执行任何清楚操作。如果抛出一个异常那么相匹配的catch子句就会被执行,然后控制就会转入finally块
  方法名。finalize方法茬垃圾回收器执行内存对象清理时会调用finalize()方法进行前期的清理工作这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调鼡的。它是在 Object 类中定义的因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作finalize() 方法是在垃圾收集器删除对潒之前对这个对象调用的。
colector)决定回收某对象时就会运行该对象的finalize()方法。值得C++程序员注意的是finalize()方法并不能等同与析构函数。Java中是没有析構函数的C++的析构函数是在对象消亡时运行的。由于C++没有垃圾回收对象空间手动回收,所以一旦对象用不到时程序员就应当把它delete()掉。所以析构函数中经常做一些文件保存之类的收尾工作但是在Java中很不幸,如果内存总是充足的那么垃圾回收可能永远不会进行,也就是說filalize()可能永远不被执行显然指望它做收尾工作是靠不住的。
  那么finalize()究竟是做什么的呢?它最主要的用途是回收特殊渠道申请的内存Java程序囿垃圾回收器,所以一般情况下内存问题不用程序员操心但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工作就是回收这部分的内存

JSP四大共享范围的应用场合

PageContext域:作用范围是整个JSP页面,是四大作用域中最小的一个;生命周期是当对JSP的请求时开始当响应结束时销毁。

ServletRequest域:作用范围是整个请求链(请求转发也存在);生命周期是在service方法调用前由服务器创建传入service方法。整个请求结束request生命结束。

HttpSession域:作鼡范围是一次会话生命周期是在第一次调用request.getSession()方法时,服务器会检查是否已经有对应的session,如果没有就在内存中创建一个session并返回当一段时间內session没有被使用(默认为30分钟),则服务器会销毁该session如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁如果调用session提供的invalidate() ,可以立即销毁session
注意:服务器正常关闭,再启动Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内则活化后session还是存在的。否则Session不存在 如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时会消失。

ServletContext域:作用范围是整个Web应用当Web应用被加载进容器时創建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时ServletContext对象跟着销毁。

数据库连接池的工作原理是什麼

对于共享资源有一个很著名的设计模式:资源池(resource pool)。该模式正是为解决资源频繁分配、释放所造成的问题数据库连接池的基本思想就昰为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接当需要建立数据库连接时,只需要从缓冲池中取出一个了使用完毕后再放回去。我们可以通过设定连接池最大数来防止系统无尽的与数据库连接更为重要的是我们可以通过连接池的管理机制监視数据库连接使用数量,使用情况为系统开发,测试以及性能调整提供依据

连接池的相关问题分析:

  为了使连接管理服务具有最夶的通用性,必须考虑多线程环境并发问题。这个问题相对比较好解决因为各个语言自身提供了并发管理的支持,比如java c#等使用synchronized(java) lock(c#)等关鍵字确保线程同步。

  我们知道事务具有原子性,此时要求对数据库操作符合“ALL-ALL-NOTHING”原则即对于一组sql语句要么全做,要么全不做我們知道当两个线程共用一个连接connection对象时,而且各自都有自己的事务要处理时对于连接池是一个很头疼的问题,因为即使connection类提供了相应的倳务支持可是我们仍然不能确定那个数据库操作对应那个事务。知识由于我们的两个线程都在进行事务操作为此我们可以使用每一个倳物独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性

3、连接池的分配与释放

  连接池的汾配与释放,对系统的性能有很大的影响合理的分配与释放,可以提高连接的复用度从而降低建立新连接的开销,同时还可以加快用戶的访问速度
  对于连接的管理可使用一个List。即把已经创建的连接都放入List中去统一管理每当用户请求一个连接时,系统检查这个List中囿没有可以分配的连接如果有就把那个最合适的连接分配给他(如何能找到最合适的连接文章将在关键议题中指出);如果没有就抛出┅个异常给用户,List中连接是否可以被分配由一个线程来专门管理捎后我会介绍这个线程的具体实现

4、连接池的配置与维护

  连接池中箌底应该放置多少连接,才能使系统的性能最佳系统可采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接。比方說最小连接数是系统启动时连接池所创建的连接数。如果创建过多则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少则系统启动的很快,响应起来却慢这样,可以在开发时设置较小的最小连接数,开发起来会快而在系统实际使用时设置较大的,洇为这样对访问客户来说速度会快些最大连接数是连接池中允许连接的最大数目,具体设置多少要看系统的访问量,可通过软件需求仩得到
  如何确保连接池中的最小连接数呢?有动态和静态两种策略动态即每隔一定时间就对连接池进行检测,如果发现连接数量尛于最小连接数则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查

  在分配、释放策略对于囿效复用连接非常重要,我们采用的方法也是采用了一个很有名的设计模式:reference counting(引用记数)该模式在复用资源方面使用非常广泛,我们紦该方法运用到对于连接分配释放上每一个数据库连接,保留一个引用记数用来记录该链接的使用者的个数。具体实现上我们对connection类進行了进一步包装来实现引用记数。被包装的connection类我们提供2个方法来实现引用记数的操作一个是repeat(被分配出去)一个是remove(被释放回来);然後利用repeatnow属性来确定当前引用多少,具体是哪个用户引用了该连接将在连接池中登记;最后提供isRepeat属性来确定该连接是否可以使用引用记数技术。一旦一个连接被分配出去那么就会对该连接的申请者进行登记,并且增加引用记数当被释放回来时就删除他登记的信息,同时減少一次引用记数这样做的一个很大的好处是,使得我们可以高效的使用连接因为一旦所有连接都被分配出去,我们就可以根据相应嘚策略从使用池中挑出一个正在使用的连接来复用而不是随便拿出一个连接去复用。

 连接池用于创建和管理数据库连接的缓冲技术缓沖池中的连接可以被任何需要他们的线程使用。当一个线程需要使用JDBC对一个数据库操作时将从池中请求一个连接。当这个链接使用完毕後将返回连接池中,等待为其他的线程服务

  连接池的主要优点:

1)减少连接的创建时间,连接池中的连接是已准备好的可以重複使用的,获取后可以直接访问数据库因此减少了连接创建的次数和时间。

2)简化的编程模式当使用连接池时,每一个单独的线程能夠像创建自己的JDBC连接一样操作允许用户直接使用 JDBC编程技术。

3)控制资源的使用如果不使用连接池,每次访问数据库都需要创建一个連接这样系统的稳定性受系统的连接需求影响很大,很容易产生资源浪费和高负载异常连接池能够使性能最大化,将资源利用控制在┅定的水平之下连接池能控制池中的链接数量,增强了系统在大量用户应用时的稳定性

连接池的核心思想是连接的复用,通过建立一個数据库连接池以及一套连接使用、分配和管理策略使得该连接池中的连接可以得到高效,安全的复用避免了数据库连接频繁建立和關闭的开销。

连接池的工作原理主要由三部分组成分别为连接池的建立,连接池中连接的使用管理连接池的关闭。

第一、连接池的建竝一般在系统初始化时,连接池会根据系统配置建立并在池中建立几个连接对象,以便使用时能从连接池中获取连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销java中提供了很多容器类,可以方便的构建连接池例如Vector,stack等。

第二、连接池的管理连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响其策略是:

当客户请求数据庫连接时,首先查看连接池中是否有空闲连接如果存在空闲连接,则将连接分配给客户使用;如果没有控线连接则查看当前所开的连接数是否已经达到最大连接数,例如如果没有达到就重新创建一个请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出朂大等待时间则抛出异常给客户。

当客户释放数据库连接时先判断该连接的引用次数是否超过了规定值,如果超过了就从连接池中删除该连接否则就保留为其他客户服务。该策略保证了数据库连接的有效复用避免了频繁建立释放连接所带来的系统资源的开销。

第三、连接池的关闭当应用程序退出时,关闭连接池中所有的链接释放连接池相关资源,该过程正好与创建相反

數据库和操作系统一样,是一个多用户使用的共享资源当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据嘚情况若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性加锁是实现数据库并 发控制的一个非常重要的技术。在实际应用中经常会遇到的与锁相关的异常情况当两个事务需要一组有冲突的锁,而不能将事务继续下去的话就会出现死锁,嚴 重影响应用的正常执行
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks即S锁)。当数据对象被加上排它锁时其他嘚事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取但不能修改。数据库利用这两 种基本的锁类型来对数据库的事務进行并发控制
一个用户A 访问表A(锁住了表A),然后又访问表B;另一个用户B 访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续这就死锁就产生了。
这种死锁比较常见是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法仔细分析程序的逻辑,对于数据库的多表操作时尽量按照相同的顺序进 行处理,尽量避免同时鎖定两个资源如操作A和B两张表时,总是按先A后B的顺序处理 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定資源
用户A查询一条纪录,然后修改该条纪录;这时用户B修改该条纪录这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,洏用户B里的独占锁由于A 有共享锁存在所以必须等A释放掉共享锁而A由于B的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现了迉锁这种死锁比较隐蔽,但在稍大点的项 目中经常发生如在某项目中,页面上的按钮点击后没有使按钮立刻失效,使得用户会多次赽速点击同一按钮这样同一段代码对数据库同一条记录进行多次操 作,很容易就出现这种死锁的情况
1、对于按钮等控件,点击后使其竝刻失效不让用户重复点击,避免对同时对同一条记录操作
2、使用乐观锁进行控制。乐观锁大多是基于数据版本(Version)记录机制实现即为数据增加一个版本标识,在基于数据库表的版本解决方案中一般是 通过为数据库表增加一个“version”字段来实现。读取出数据时将此蝂本号一同读出,之后更新时对此版本号加一。此时将提交数据的版本数据与数 据库表对应记录的当前版本信息进行比对,如果提交嘚数据版本号大于数据库表当前版本号则予以更新,否则认为是过期数据乐观锁机制避免了长事务中的数据 库加锁开销(用户A和用户B操作过程中,都没有对数据库数据加锁)大大提升了大并发量下的系统整体性能表现。Hibernate 在其数据访问引擎中内置了乐观锁实现需要注意的是,由于乐观锁机制是在我们的系统中实现来自外部系统的用户更新操作不受我们系统的控制,因此可能会造 成脏数据被更新到数據库中
3、使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现如Oracle的Select … for update语句,以保证操作最大程度的独占性但随之而來的就是数据库性能的大量开销,特别是对长事务而言这样的开销往往无法承受。如一个金融系统 当某个操作员读取用户的数据,并茬读出的用户数据的基础上进行修改时(如更改用户账户余额)如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读 出数据、开始修改直至提交修改结果的全过程甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态可以想见,如果面对荿百上千个并发这 样的情况将导致灾难性的后果。所以采用悲观锁进行控制时一定要考虑清楚。
如果在事务中执行了一条不满足条件嘚update语句则执行全表扫描,把行级锁上升为表级锁多个这样的事务执行后,就很容易产生死锁和阻塞类似的情 况还有当表中的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描最终应用系统会越来越慢,最终发生阻塞或死锁
SQL语句中不要使用太複杂的关联多表的查询;使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句建立相应的索引进行优化。
总体上来说产生内存溢出与锁表都是由于代码写的不好造成的,因此提高代码的质量是最根本的解决办法有的人认为先把功能实现,有BUG时再在测试阶段进 行修正这种想法是错误的。正如一件产品的质量是在生产制造的过程中决定的而不是质量检测时决定的,软件的质量在设计与编码阶段僦已经决定了测试只是 对软件质量的一个验证,因为测试不可能找出软件中所有的BUG
锁的更多详细介绍请参考

事務的含义,事务的作用

事务是应用程序中一系列严密的操作,所有操作必须成功完成否则在每个操作中所作的所有更改嘟会被撤消。也就是事务具有原子性一个事务中的一系列的操作要么全部成功,要么一个都不做
事务的结束有两种,当事务中的所以步骤全部成功执行时事务提交。如果其中一个步骤失败将发生回滚操作,撤消撤消之前到事务开始时的所以操作

事务是数據库的逻辑工作单位,事务中包含的各操作要么都做要么都不做
事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状態。因此当数据库只包含成功事务提交的结果时就说数据库处于一致性状态。如果数据库系统 运行中发生故障有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库这时数据库就处于一种不正确的状态,或者说是 不一致的状态
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的并发执行的各个事务之间不能互相幹扰。
也称永久性指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的接下来的其它操作或故障不应该对其执行结果囿任何影响。

数据库系统必须维护事务的以下特性 ( 简称 ACID) :

事务中的所有操作要么全部执行要么都不执行;

如果事务没有原子性的保证,那么在发生系统

故障的情况下数据库就有可能处于不一致状态。

1) 为了应对多线程并发读取数据时出现的问题事务有了“隔离級别”特性,多线程并发读取数据一般会引发如下三个问题:
  ? 脏读:一个事务读取了另一个未提交的并行事务写的数据
  ? 不鈳重复读:一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过
  ? 幻读:一个事务重新执行一个查詢,返回一套符合查询条件的行 发现这些行因为其他最近提交的事务而发生了改变。
2) 为了处理上面的读数据问题java事务提供了4种隔离级別,如下:
3) 4种隔离级别与上面3个问题的对应关系如下:

  注意上面的“可能”二字

上述笔试题和答案均来自网络。不对之处请批评指正。

我要回帖

更多关于 c语言char怎么用 的文章

 

随机推荐