myJavaBlog

java世界
随笔 - 43, 文章 - 0, 评论 - 2, 引用 - 0
数据加载中……

置顶随笔

[置顶]教你如何将普通表转换为分区表

需求描述:
一个表已经上线,但是上线之后发现该表的数据量很大,而且会删除历史数据,该表上要建立多个唯一索引,现在的问题就是在建表的时候是建立了一个普通表,现在需要将普通表转化为分区表,并尽量减少对应用的影响
1、使用ctas的方式来建立
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)----原表


---建立分区表:
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
as
select * from t1;----此时应用还是不断的往t1表中插入数据-


alter table t1_new add constraints pk_t1_new primary key (id) using tablespace local index_tablespace;----建立本地索引为了删除历史数据
/alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


但是应用还在outer_id上建立唯一索引
create unique index IDX_t1_new_2 on t1_new (OUTER_ID) LOCAL ;
此时报


ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集
原来oracle不支持在分区表上创建PK主键时主键列不包含分区列,创建另外的约束(unique)也不可以。
为了解决这个问题,两种方法
1、将分区键加到唯一索引里面
2、将local索引变为global索引----此时当进行历史数据删除的时候会导致索引失效
权衡之后在outer_id上建立普通索引




alter table t1 rename to t1_bak;
alter table t1_new rename to t1;
在进行ctas之后需要进行数据完整新检查,而且在进行rename的时候会导致应用连接失效(也有可能在进行alter的时候获取不到表锁而失败)---适用于修改不很频繁的表


2、使用交换分区的方式
----原表
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)
alter table t1 add constraints pk_t1 primary key(id) ;


新表
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


ALTER TABLE t1_new EXCHANGE PARTITION p_t1_new WITH TABLE t1 without validation;----要不要加上without validation(加上的话就是不验证数据是否有效,直接全部放在p_t1_new分区中)
然后进行rename操作


优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。
不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。
适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。


3、在线重定义
----原表
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)
alter table t1 add constraints pk_t1 primary key(id) ;


新表
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T1', DBMS_REDEFINITION.CONS_USE_PK);

EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T1', 'T1_NEW',DBMS_REDEFINITION.CONS_USE_PK);
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]

[url=http://www.d9732.com]澳门博彩[/url]

posted @ 2012-04-19 15:31 夏凡 阅读(1135) | 评论 (0)编辑 收藏

[置顶]聊聊关于请求重定向与请求发的比较

尽管httpservletresponse.sendredirect方法和requestdispatcher.forward方法都可以让浏览器获得另外一个url所指向的资源,但两者的内部运行机制有着很大的区别。下面是httpservletresponse.sendredirect方法实现的请求重定向与requestdispatcher.forward方法实现的请求转发的总结比较:

(1)requestdispatcher.forward方法只能将请求转发给同一个web应用中的组件;而httpservletresponse.sendredirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对url重定向到其他站点的资源。如果传递给httpservletresponse.sendredirect 方法的相对url以“/”开头,它是相对于整个web站点的根目录;如果创建requestdispatcher对象时指定的相对url以“/”开头,它是相对于当前web应用程序的根目录。

(2)调用httpservletresponse.sendredirect方法重定向的访问过程结束后,浏览器地址栏中显示的url会发生改变,由初始的url地址变成重定向的目标url;而调用requestdispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的url地址不变。

(3)httpservletresponse.sendredirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个url的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。requestdispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。

(4)requestdispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而httpservletresponse.sendredirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个web应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用httpservletrequest.setattribute方法传递预处理结果,那就应该使用requestdispatcher.forward方法。不同web应用程序之间的重定向,特别是要重定向到另外一个web站点上的资源的情况,都应该使用httpservletresponse.sendredirect方法。

(5)无论是requestdispatcher.forward方法,还是httpservletresponse.sendredirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。  
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url]

posted @ 2012-04-19 14:34 夏凡 阅读(216) | 评论 (0)编辑 收藏

[置顶]简单介绍java中Runtime类和Process类

在java.lang包当中定义了一个Runtime类,在java中对于Runtime类的定义如下:
public class Runtime
extends Object
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。
根据上面的话,我们知道对于每一个java程序来说都只有一个Runtime类实例,而且不能由用户创建一个Runtime实例,既然不能创建那么这个类的实例的作用是什么呢?它提供了应用程序和应用程序正在运行的环境的一个接口。Runtime不能由我们创建,我们可以通过Runtime类的一个静态方法,得到一个Runtime类的实例。获取了这个实例之后我们就可以获取java虚拟机的自由内存、也可以获取这个java虚拟机的总的内存等(具体的方法可以参照java帮助文档Runtime类的方法学习),也就是说这个类提供了应用程序了环境的接口。下面我们举一个例子程序:
Runtime rt=Runtime.getRuntime();
System.out.println(rt.freeMemory());
System.out.println(rt.totalMemory());//结果返回的是数字
Runtime类还有一个好处就是可以执行一个外部的程序,可以调用Runtime类的exec()方法传入一个命令(exec()方法有几个重载的方法,可以自己学习),创建一个子进程,结果返货一个Process类的实例,通过这个实例我们可以管理创建的子进程。对于Process类在java帮助文档中描述如下:
public abstract class Process
extends Object
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

public abstract class Process
extends Object
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
下面我们接着上面的代码继续写:
try{
rt.exec("notepad");}
catch(Exception e){
e.printStackTrace;}//在使用exec()方法的时候会抛出一个异常,我们需要捕获
这段代码,是运行在windows上的,它调用了windows系统的记事本程序。举一反三我们同样可以用这个方法去编译java的文件,只是传入的参数是“javac ***.java”。
对于Process类的实例主要作用是创建一个可以管理的进程,并对它进行管理。Process类还有几个方法分别是destroy() 杀掉子进程、exitValue()返回子进程的出口值、getErrorStream()获取子进程的错误流,错误流获得由该 Process 对象表示的进程的错误输出流传送的数据,还有获取输入流输出流请读者自己参照java帮助文档学习。
这是自己在接触Runtime类和Process类的时候学到的一些东西,分享出来希望对大家有用,大家看见了若是有不对的地方,请指出来。 
(转载请注明出处:[url=http://www.live588.org]淘金盈[/url]
[url=http://www.10086money.com]时尚资讯[/url])

posted @ 2012-04-19 10:21 夏凡 阅读(818) | 评论 (0)编辑 收藏

[置顶]关于Java多线程1—程序、进程、线程的一些比较

许多人对于程序、进程、线程这几个概念许多人都分的不是很清楚,下面我们就简单的介绍一下它们的区别。

程序是计算机指令的集合,它以文件的形式存储在磁盘上。程序是通常我们所写好的存储于计算机上没有执行的指令的集合,通俗的讲就是我们自己写的代码。我们写的代码不可能只是为了存储吧,必须运行才不会浪费我们的辛苦,等到我们将我们的代码运行了,就产生了进程。

进程:是一个程序在其自身的地址空间中的一次执行活动。通常的程序是不能并发执行的。为了使程序能够独立运行,应该为之配置一些进程控制块,即PCB;而由程序段,相关数据段和PCB三部分构成了进程实体。通常我们并不区分进程和进程实体,基本上就代表同一事物。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。

20世纪60年代人们提出了进程的概念,在OS中一直都是以进程作为能独立运行和拥有资源的基本单位。但是进程间的切换比较麻烦费时,所以在20世纪80年代人们为了提高系统内程序并发执行的程度,进一步提高系统的吞吐量,提出了比进程更小的能独立运行的基本单位。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。一个进程可以同时拥有一个或者多个线程,这几个线程共享同样的数据。

现在的CPU几乎都是多核的了,这样多线程的程序,运行起来就更加流畅。下面我们通过图片来比较一下单线程和多线程:


这个就好比我们算一道数学题(2+3)*(5-3),如果我们使用左边的单线程,只能是先算2+3然后算5-3,最后结果相加。但是如果我们使用右边的多线程,我们可以同时对2+3和5-3进行运算,然后再对最后的结果相加。我想哪个运行的比较快就不用说了,另外多线程在图像处理,多用户通信等方面用户都很多。

可能读者会说如果我们用的是单CPU的PC那么他们就差别不大了,但是现在的事实是现在的PC基本都是多核了,所以多线程是为了我们更好的将程序移植到多核的CPU上。还有一点就是对于线程的切换,比进程的切换速度快的多,多线程更好的发挥CPU的效率。

写的不好,如果哪里错了希望大家指出。希望对你有帮助。
(转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url]

[url=http://www.9gds.com]易博网[/url])

posted @ 2012-04-19 10:19 夏凡 阅读(276) | 评论 (0)编辑 收藏

[置顶]如何使用java读取Properties文件来改变实现类

用java读取Properties文件来改变实现类的Demo:


public abstract class Vehicle {
public abstract void run();
}


public class Car extends Vehicle{
public void run(){
System.out.println("with Car");
}
}


public class Broom extends Vehicle {
@Override
public void run() {
System.out.println("Broom");
}
}


test.properties 中:
VehicleType=abstractfactory.step4properties.Broom
注意:该文件要放在src目录下,且等号两边不可有空格




import java.util.Properties;
public class Test {
public static void main(String[] args) throws Exception{
Properties pros = new Properties();
///配置文件编译之后放在bin目录下
//每个class的类,都会被当作Class对象。getClassLoader:拿到了装载这个Class的装载器
///把它当作一个流读进来,默认路径是根目录。读出来之后,把它转化为一个properties对象,然后,等号左边的就是key,等号右边的就是value
pros.load(Test.class.getClassLoader().getResourceAsStream("abstractfactory/step4properties/spring.properties"));

String vehicleTypeName = pros.getProperty("VehicleType");
System.out.println(vehicleTypeName);


///现在,得到的字符串,我们想把字符串代表的类,产生一个对象,用到反射
///Class.forName把字符串所代表的表装到内存,newInstance:生成对象,得到的是个Object
Vehicle v = (Vehicle)Class.forName(vehicleTypeName).newInstance();
v.run();
//只要改变test.properties中的VehicleType=factory.step4Spring.Broom,即可实现改变实现类的功能。
}
}
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]
[url=http://www.d9732.com]澳门博彩[/url])

posted @ 2012-04-19 10:05 夏凡 阅读(924) | 评论 (0)编辑 收藏

[置顶]教你关于JSP连接MYSQL5的中文问题解决方法

用JAVA/JSP做开发很久了,也见过许多朋友做过,有很大一部分用的是MYSQL的数据库,现在MYSQL数据库版本5.0及以上的都已经被用的很广泛了,但一直有一个问题,使刚入门的朋友费劲心思.就是JSP连接MYSQL5数据库的时候的一些中文问题.于是网络上也出现了很多相关的帖子.由些大家对MYSQL5数据库的配制文件MY.INI也有了些了解.甚至一些朋友就直接问:你们的MYSQL是什么编码的?你们的TOMCAT是什么样的编码,可能不是很规范的问法,但说明了编码问题的确影响了大家的使用.

下面的讲解是在MYSQL5.0.18,TOMCAT5.0.28,驱动为mysql-connector-java-3.2.0-alpha-bin.jar及以上版本的情况下测试的

JSP连接数据库的乱码问题,分两部分来看

1 数据库中是不是乱码?

我们需要保证数据库保存的不是"?????"形式的乱码,如何保证呢?

我们在管理MYSQL数据库的时候,需要用一个客户端,无论你用MYSQL-FRONT,EMS SQL Manager for MySQL,还是MYSQL命令行,这些都是客户端,也是程序连接了数据库,我们现在用客户端EMS SQL Manager for MySQL连接数据库,连接的时候一定要设置客户端字符集为GBK或者GB2312,这样你才能知道数据库里面是不是乱码.这一编码设置很重要,不然,就算数据库里是中文,你看到的还是乱码

这样连接后,我们看下我们做测试的表格,里面的汉字就是正常的,这个时候也可以直接在上面的记录中进入中文的修改

若这里没有选择编码的话,一般默认的就是UTF8的了,连接后再看这个表格,就会出现乱码

而这个时候就会出现不能插入中文的问题,若您插入中文的话,就会出现下列错误

这个时候大家什么不要误解,不是不能插入中文,也不是你插入的字符太长,

更改下连接编码就OK了.下面是这个表格的SQL语句

CREATE TABLE `test` (
`name` varchar(100) default NULL,
`adesc` varchar(100) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

二.程序连接数据时,也要设置好连接时候的编码,JSP连接MYSQL数据库时候,有个URL参数,jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8,在这里需要设置成UTF-8,

下面是连接数据库的程序代码

<%@ page contentType="text/html;charset=GB2312" language="java"%>
<%@ page import="java.io.*" %> 
<%@ page import="java.util.*" %>
<%@ page import="java.sql.*" %>

<%
out.println("您的数据库某表格中的内容如下<br>");
try {
Class.forName("com.mysql.jdbc.Driver").newInstance(); 
String url ="jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8";
//testDB为你的数据库名 
Connection conn= DriverManager.getConnection(url); 
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql="select * from test";

ResultSet rs=stmt.executeQuery(sql); 
while(rs.next()) {
out.println("第一个字段内容:<font color=red>"+rs.getString(1)+"</font> 第二个字段内容:<font color=red>"+rs.getString(2)+"</font><br>");
}
out.print("数据库操作成功,恭喜你");

sql = "insert into test (name,adesc) values ('中文','汉字')";
stmt.execute(sql);


rs.close(); 
stmt.close(); 
conn.close(); 
}
catch(Exception e){
System.out.println("数据库连接不成功"+e.toString());
}
%>

上面的经验是经过多次尝试总结出来的,不管是MYSQL的客户端还是程序连接MYSQL数据库,在本质上都是程序连接数据库,可以自己在本地多试验下,有时候有可能是驱动太旧.
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url]

posted @ 2012-04-19 09:58 夏凡 阅读(211) | 评论 (0)编辑 收藏

[置顶]你懂得如何用QTP录制鼠标右键点击事件吗

qtp录制鼠标右键单击事件要通过模拟键盘操作来实现

step 1,修改replaytype为2,一般情况默认设置是1的。(1 – 使用浏览器事件运行鼠标操作。 2 – 使用鼠标运行鼠标操作)
setting.webpackage(”replaytype”) = 2

step 2,鼠标右键单击事件
(附:click的事件有三种 micleftbtn 0 鼠标左键。 micrightbtn 1 鼠标右键。 micmiddlebtn 2 鼠标中键)
browser(”支付宝 – 网上支付 安全快速!”).page(”支付宝 – 网上支付 安全快速!”).link(”返回我要付款”).click , , micrightbtn

step 3,点击右键弹出的菜单(采用键盘事件来模拟)
set wshshell = createobject(”wscript.shell”)
wshshell.sendkeys “{down}” //键盘向下的箭头
wshshell.sendkeys “{down}”
wshshell.sendkeys “{enter}” //回车键

step 4,修改replaytype为1(使用浏览器事件运行鼠标操作)
setting.webpackage(”replaytype”) = 1

good to go now. 
(转载请注明出处:[url=http://www.live588.org]淘金盈[/url]
[url=http://www.10086money.com]时尚资讯[/url])

posted @ 2012-04-19 09:51 夏凡 阅读(446) | 评论 (0)编辑 收藏

[置顶]通过jquery 获取父窗口的元素 父窗口 子窗口的方法

     摘要: $("#父窗口元素ID",window.parent.document); 对应javascript版本为window.parent.document.getElementByIdx_x("父窗口元素ID"); 取父窗口的元素方法:$(selector, window.parent.document); 那么你取父窗口的父窗口的元素就可以用:$(selector, w...  阅读全文

posted @ 2012-04-19 09:49 夏凡 阅读(478) | 评论 (0)编辑 收藏

[置顶]教你使用C# 实现文件锁

     摘要: C#代码  using System;  using System.Collections.Generic;  using System.ComponentModel;  using System.Data;  using System.Drawin...  阅读全文

posted @ 2012-04-19 09:43 夏凡 阅读(1076) | 评论 (0)编辑 收藏

[置顶]教你如何用java取得web工程目录

     摘要: 1.可以在servlet的init方法里 String path = getServletContext().getRealPath("/"); 这将获取web项目的全路径 例如 :E:\eclipseM9\workspace\tree\ tree是我web项目的根目录 2.你也可以随时在任意的class里调用 this.getClass...  阅读全文

posted @ 2012-04-19 09:39 夏凡 阅读(7805) | 评论 (1)编辑 收藏

[置顶]教你如何使用Maven模板生成一个项目

     摘要: Maven带有超过40+个Maven模板,让开发者快速开始一个新的Java项目。这一章,演示怎样使用Maven的命令“mvn archetype:generate”生成一个新的Java Web项目。 下面是使用Maven模板生成项目的步骤。 1、mvn archetype:generate命令 定位到要生成的项目的目录下,如“D:\...  阅读全文

posted @ 2012-04-19 09:33 夏凡 阅读(2086) | 评论 (0)编辑 收藏

[置顶]教你认识和理解spring声明式事务管理

Spring也提供了声明式事务管理。这是通过Spring AOP实现的。 

Spring 中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通java类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的, spring在这段时间内通过拦截器,加载事务切片。原理就是这样,具体细节请参考jdk中有关动态代理的文档。本文主要讲解如何在spring中进行事务控制。 
动态代理的一个重要特征是,它是针对接口的,所以我们的dao要通过动态代理来让spring接管事务,就必须在dao前面抽象出一个接口,当然如果没有这样的接口,那么spring会使用CGLIB来解决问题,但这不是spring推荐的方式,所以不做讨论. 

大多数Spring用户选择声明式事务管理。这是最少影响应用代码的选择, 因而这是和非侵入性的轻量级容器的观念是一致的。 

从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。 它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上 下文调用setRollbackOnly()方法。不同之处如下: 

不象EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作 

Spring可以使声明式事务管理应用到普通Java对象,不仅仅是特殊的类,如EJB 

Spring提供声明式回滚规则:EJB没有对应的特性, 我们将在下面讨论这个特性。回滚可以声明式控制,不仅仅是编程式的 

Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务 回滚中插入定制的行为。你也可以增加任意的通知,就象事务通知一样。使用 EJB CMT,除了使用setRollbackOnly(),你没有办法能 够影响容器的事务管理 

Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如 果你需要这些特性,我们推荐你使用EJB。然而,不要轻易使用这些特性。通常我 们并不希望事务跨越远程调用 

回滚规则的概念是很重要的:它们使得我们可以指定哪些异常应该发起自 动回滚。我们在配置文件中,而不是Java代码中,以声明的方式指定。因此,虽然我们仍 然可以编程调用TransactionStatus对象的 setRollbackOnly()方法来回滚当前事务,多数时候我们可以 指定规则,如MyApplicationException应该导致回滚。 这有显著的优点,业务对象不需要依赖事务基础设施。例如,它们通常不需要引 入任何Spring API,事务或其他任何东西。 

EJB的默认行为是遇到系统异常(通常是运行时异常), EJB容器自动回滚事务。EJB CMT遇到应用程序异常 (除了java.rmi.RemoteException外的checked异常)时不 会自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked 异常自动回滚事务),但是这是可以定制的。 

按照我们的测试,Spring声明式事务管理的性能要胜过EJB CMT。 

通常通过TransactionProxyFactoryBean设置Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBean时,必须提供一个相关的 PlatformTransactionManager的引用和事务属性。 事务属性含有上面描述的事务定义。 

<bean id="petStore"     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
<property name="transactionManager"><ref bean="transactionManager"/></property> 
    <property name="target"><ref bean="petStoreTarget"/></property>  
  <property name="transactionAttributes">        <props>            <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>            <prop key="update*">PROPAGATION_REQUIRED</prop>            <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>        </props>    </property></bean> 
code] 
事务代理会实现目标对象的接口:这里是id为petStoreTarget的bean。(使用 CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true就可以。如果目标对象没有实现任何接口,这将自动设置该属性为true。通常,我们希望面向接口而不是类编程。)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的(一般来说是个好想法)。也可以通过从 org.springframework.aop.framework.ProxyConfig继承或所有AOP代理工厂共享 的属性来定制TransactionProxyFactoryBean的行为。 

这里的transactionAttributes属性定义在 org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 中的属性格式来设置。这个包括通配符的方法名称映射是很直观的。注意 insert*的映射的值包括回滚规则。添加的-MyCheckedException 指定如果方法抛出MyCheckedException或它的子类,事务将 会自动回滚。可以用逗号分隔定义多个回滚规则。-前缀强制回滚,+前缀指定提交(这允许即使抛出unchecked异常时也可以提交事务,当然你自己要明白自己 在做什么)。 

TransactionProxyFactoryBean允许你通过 “preInterceptors”和“postInterceptors”属性设置“前”或“后”通知来提供额外的 拦截行为。可以设置任意数量的“前”和“后”通知,它们的类型可以是 Advisor(可以包含一个切入点), MethodInterceptor或被当前Spring配置支持的通知类型 (例如ThrowAdvice, AfterReturningtAdvice或BeforeAdvice, 这些都是默认支持的)。这些通知必须支持实例共享模式。如果你需要高级AOP特 性来使用事务,如有状态的maxin,那最好使用通用的 org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean实用代理创建者。 

也可以设置自动代理:配置AOP框架,不需要单独的代理定义类就可以生成类的 代理。 

附两个spring的事务配置例子: 
<prop key="add"> 
     PROPAGATION_REQUIRES_NEW, -MyException 
</prop> 
注:上面的意思是add方法将独占一个事务,当事务处理过程中产生MyException异常或者该异常的子类将回滚该事务。 

<prop key="loadAll"> 
    PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly 
</prop> 
注:表示loadAll方法支持事务,而且不会读取没有提交事务的数据。它的数据为只读(这样有助于提高读取的性能) 

附A Spring中的所有事务策略 

PROPAGATION_MANDATORY 
PROPAGATION_NESTED 
PROPAGATION_NEVER 
PROPAGATION_NOT_SUPPORTED 
PROPAGATION_REQUIRED 
PROPAGATION_REQUIRED_NEW 
PROPAGATION_SUPPORTS 

附B Spring中所有的隔离策略: 

ISOLATION_DEFAULT 
ISOLATION_READ_UNCOMMITED 
ISOLATION_COMMITED 
ISOLATION_REPEATABLE_READ 
ISOLATION_SERIALIZABL 
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url])

posted @ 2012-04-18 21:16 夏凡 阅读(324) | 评论 (0)编辑 收藏

[置顶]认识java反射与代理

     摘要: java反射与代理 一. 关于数据库. 当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作...  阅读全文

posted @ 2012-04-18 21:14 夏凡 阅读(248) | 评论 (0)编辑 收藏

[置顶]分享关于JMS与WebService负载均衡

众所周知,当多个消息消费者(MessageConsumer)同时监听同一个消息队列(Queue)的时候,JMS提供者会在它们之间提供一种负载均衡机制,从而达到可以同时处理多个消息的目的。图一是一个简单的示意图,当消息生产者发送多个消息时,JMS提供者会把这些消息均匀的分发到不同的消息消费者。  


  图一 JMS负载均衡示意图

  一、WebService负载均衡
  要在原来的WebService上应用负载均衡,首先应该明确一个前提,就是客户端和服务端应尽可能的不做修改。另外还需要确保可以方便的添加和删除一个Service节点,而不会影响整个应用的运行。庆幸的是WebService调用通常都是无状态的,类似于无状态会话 Bean(Stateless Session Bean)的远程调用,服务端和客户端不需要维持一个会话,也就是说同一个客户端调用多次WebService请求,每个请求可以由不同的Service 为它服务,这样就可以避免Session复制的问题,如果一个Service崩溃了,另一个Service可以继续为客户端服务。
  二、将JMS负载均衡应用到WebService中
  接下来就把JMS的负载均衡机制应用到WebService当中去,图二是一个整体的框架图,Proxy作为一个WebService的代理来和客户端交互, 而Listener会去掉用具体的WebService,来完成一次WebService方法的调用。


  图二 整体框架图

  与客户端直接交互的是Proxy,它是一个简单的Servlet,它的作用就是拦截客户端发送过来的请求,提取请求中的SOAP包的内容,然后把它封装成一个消息发送到指定的Queue中去,同时它会等待消息的回复,因为回复的消息中包含着WebService调用返回的结果,后面会详细讲到。当Proxy收到回复消息之后,读取其中的内容并把它返回给客户端,从而完成一个WebService的调用。另外需要注意的是,在这里Proxy需要区分出客户端发出的是GET请求,还是POST请求。如果是GET请求,就有可能是客户端正在获取WebService的WSDL。如果是POST请求,那么通常就是客户端在调用一个WebService方法了。下面是一个简单的Proxy实现:
  1   public class ServiceProxy extends HttpServlet {
  2
  3   private ConnectionFactory factory;
  4
  5   private Connection connection;
  6
  7   private Queue queue;
  8
  9   public void init() throws ServletException {
  10
  11   super.init();
  12
  13   try {
  14
  15   //在这里为了简单起见,采用了ActiveMQ。在实际的J2EE应用中应通过JNDI查找相应的ConnectionFactory和Queue。|||
  16
  17   factory = new ActiveMQConnectionFactory("vm://localhost");
  18
  19   connection = factory.createConnection();
  20
  21   connection.start();
  22
  23   queue = new ActiveMQQueue("testQueue");
  24
  25   } catch (JMSException e) {
  26
  27   e.printStackTrace();
  28
  29   }
  30
  31   }
  32
  33   protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  34
  35   if (req.getQueryString().endsWith("wsdl") || req.getQueryString().endsWith("WSDL")) {
  36
  37   try {
  38
  39   Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  40
  41   Message message = session.createMessage();
  42
  43   //这个属性用来标示请求是否是WSDL请求,后面的Listener会根据它来调用具体的WebService。
  44
  45   message.setBooleanProperty("isWsdl", true);
  46
  47   message.setJMSReplyTo(session.createTemporaryQueue());
  48
  49   session.createProducer(queue).send(message);
  50
  51   //等待回复消息,它里面包含Service返回的WSDL,这里使用了一个选择器。
  52
  53   String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID());
  54
  55   MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector);
  56
  57   TextMessage replyMessage = (TextMessage) consumer.receive();
  58
  59   //将WSDL返回给客户端。
  60
  61   resp.getWriter().write(replyMessage.getText());
  62
  63   } catch (Exception e) {
  64
  65   e.printStackTrace();
  66
  67   }
  68
  69   }
  70
  71   }
  72
  73   protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
  74
  75   try {
  76
  77   //首先从客户端请求中得到SOAP请求部分。
  78
  79   StringBuffer payLoad = new StringBuffer();
  80
  81   BufferedReader reader = req.getReader();
  82
  83   String temp;
  84
  85   while ((temp = reader.readLine()) != null) {
  86
  87   payLoad.append(temp);
  88
  89   }
  90
  91   //将SOAP请求封装成一个消息,发送到Queue。
  92
  93   Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  94
  95   Message message = session.createTextMessage(payLoad.toString());
  96
  97   message.setBooleanProperty("isWsdl", false);
  98
  99   message.setJMSReplyTo(session.createTemporaryQueue());
  100|||
  101   session.createProducer(queue).send(message);
  102
  103   //等待回复,回复的消息中包含着服务端返回的SOAP响应。
  104
  105   String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID());
  106
  107   MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector);
  108
  109   TextMessage replyMessage = (TextMessage) consumer.receive();
  110
  111   //将SOAP响应返回给客户端。
  112
  113   resp.getWriter().write(replyMessage.getText());
  114
  115   } catch (Exception e) {
  116
  117   e.printStackTrace();
  118
  119   }
  120
  121   }
  122
  123   }
  接下来需要看一下Listener了。对于每一个Service都有一个Listener与之相对应,当一个Listener从Queue中取得一个消息之后,首先应该判断是否是WSDL请求。如果是WSDL请求,则向WebService发送一个GET请求,并将请求的结果,也就是WSDL封装成一个Message回复给Proxy。如果是SOAP请求,则从中取出SOAP请求部分并通过POST方法发送给Service,所得到的返回结果即为Service的SOAP响应,把它回复给Proxy,进而回复给客户端。
  下面是Listener的一个简单实现,在这里我们使用了HttpClient来发送GET和POST请求。
  1   public class Listener {
  2
  3   private ConnectionFactory factory;
  4
  5   private Connection connection;
  6
  7   private Queue queue;
  8
  9   private Session session;
  10
  11   public Listener() throws Exception {
  12
  13   //为了简单,还是采用了ActiveMQ。
  14
  15   factory = new ActiveMQConnectionFactory("vm://localhost");
  16
  17   connection = factory.createConnection();
  18
  19   connection.start();
  20
  21   queue = new ActiveMQQueue("testQueue");
  22
  23   session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  24
  25   }
  26
  27   public void startUp() throws Exception {
  28
  29   MessageConsumer consumer = session.createConsumer(queue);
  30
  31   consumer.setMessageListener(new MessageListener() {
  32
  33   public void onMessage(Message message) {
  34
  35   try {
  36
  37   String response;
  38
  39   //通过判断isWSDL这个属性来判断是否是WSDL请求。
  40
  41   if (message.getBooleanProperty("isWsdl")) {
  42
  43   //如果是WSDL请求,则向服务器发送一个GET请求,并等待WSDL响应结果。
  44
  45   HttpClient client = new HttpClient();|||
  46
  47   //具体Service的地址,可以使用properties文件等。
  48
  49   GetMethod m = new GetMethod("http://localhost:8081/hello?wsdl");
  50
  51   client.executeMethod(m);
  52
  53   response = m.getResponseBodyAsString();
  54
  55   } else {
  56
  57   //如果是SOAP请求,则将SOAP包发送给服务器,并等待SOAP响应。
  58
  59   HttpClient client = new HttpClient();
  60
  61   PostMethod m = new PostMethod("http://localhost:8081/hello");
  62
  63   m.setRequestBody(((TextMessage) message).getText());
  64
  65   client.executeMethod(m);
  66
  67   response = m.getResponseBodyAsString();
  68
  69   }
  70
  71   //将WSDL响应或SOAP响应封装成一个消息,回复给Proxy。
  72
  73   MessageProducer producer = session.createProducer(message.getJMSReplyTo());
  74
  75   TextMessage replyMessage = session.createTextMessage(response);
  76
  77   //设置JMSCorrelationID,Proxy通过它来得到该回复消息。
  78
  79   replyMessage.setJMSCorrelationID(message.getJMSCorrelationID());
  80
  81   producer.send(replyMessage);
  82
  83   } catch (Exception ex) {
  84
  85   ex.printStackTrace();
  86
  87   }
  88
  89   }
  90
  91   });
  92
  93   }
  94
  95   }
  三、还需要考虑的
  1,如果其中一个Service崩溃,我们需要停止相应的Listener,这一点可以在Listener中做到,例如当Listener访问 Service时出错,它可以等待一段时间以后再去监听Queue,同时把已经取得的消息重新发回到Queue中去,以便让其他的Listener处理。当然也可以将Listener放置到Service端,这样Service崩溃,Listener也就跟着不可用了。
  2,如果某一时刻,所有的Service都不可用,Proxy也不应该无限等待下去,而应该设置一个等待回复消息的超时期限,如果这个期限内没有收到回复消息,则表明Service都不可用,同时通知客户端。
  3,过期消息的处理,如同上一点,当Service不可用时,Proxy通知客户端出错,但是此时Proxy已经向Queue中发送了一条消息,当Service恢复时,这条消息会被重新处理。我们应该避免这种情况发生,因为这条消息已经过期了。可以设置消息的过期期限小于Proxy等待回复消息的期限,以确保它不会被重新处理。
  4,最糟糕的情况就是,Proxy或者Queue崩溃,这样就算Service正常,客户端也会调用失败。
  5,效率,既然我们选择了WebService和负载均衡,那就表示我们应该接受它效率相对低下的弱点,在这里需要说明的是JMS并不是效率的瓶颈,因为Listener只负责拿到消息并发送给Service,这时Service还是运行在多线程下的。
(转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url]

[url=http://www.9gds.com]易博网[/url]

posted @ 2012-04-18 20:30 夏凡 阅读(426) | 评论 (0)编辑 收藏

[置顶]对java hashCode的详细解读

hashCode就是我们所说的散列码,使用hashCode算法可以帮助我们进行高效率的查找,例如HashMap,说hashCode之前,先来看看Object类。

我们知道,Object类是java程序中所有类的直接或间接父类,处于类层次的最高点。在Object类里定义了很多我们常见的方法,包括我们要讲的hashCode方法,如下

 

Java代码  收藏代码
  1. public final native Class<?> getClass();  
  2. public native int hashCode();  
  3. public boolean equals(Object obj) {  
  4.   return (this == obj);  
  5. }   
  6. public String toString() {  
  7.  return getClass().getName() + "@" +  Integer.toHexString(hashCode());  
  8. }  

注意到hashCode方法前面有个native的修饰符,这表示hashCode方法是由非java语言实现的,具体的方法实现在外部,返回内存对象的地址。


在java的很多类中都会重写equals和hashCode方法,这是为什么呢?最常见的String类,比如我定义两个字符相同的字符串,那么对它们进行比较时,我想要的结果应该是相等的,如果你不重写equals和hashCode方法,他们肯定是不会相等的,因为两个对象的内存地址不一样。


String类的重写的hashCode方法

Java代码  收藏代码
  1. public int hashCode() {  
  2.     int h = hash;  
  3.     if (h == 0) {  
  4.         int off = offset;  
  5.         char val[] = value;  
  6.         int len = count;  
  7.   
  8.             for (int i = 0; i < len; i++) {  
  9.                 h = 31*h + val[off++];  
  10.             }  
  11.             hash = h;  
  12.         }  
  13.         return h;  
  14.     }  

1、这段代码究竟是什么意思?

其实这段代码是这个数学表达式的实现

Java代码  收藏代码
  1. s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]  

 s[i]是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化


2、它返回的hashCode有什么特点呢?

可以看到,String类是用它的value值作为参数来计算hashCode的,也就是说,相同的value就一定会有相同的hashCode值。这点也很容易理解,因为value值相同,那么用equals比较也是相等的,equals方法比较相等,则hashCode一定相等。反过来不一定成立。它不保证相同的hashCode一定有相同的对象。


一个好的hash函数应该是这样的:为不相同的对象产生不相等的hashCode。

在理想情况下,hash函数应该把集合中不相等的实例均匀分布到所有可能的hashCode上,要想达到这种理想情形是非常困难的,至少java没有达到。因为我们可以看到,hashCode是非随机生成的,它有一定的规律,就是上面的数学等式,我们可以构造一些具有相同hashCode但value值不一样的,比如说:Aa和BB的hashCode是一样的。


说到这里,你可能会想,原来构造hash冲突那么简单啊,那我是不是可以对HashMap函数构造很多<key,value>不都一样,但具有相同的hashCode,这样的话可以把HashMap函数变成一条单向链表,运行时间由线性变为平方级呢?虽然HashMap重写的hashCode方法比String类的要复杂些,但理论上说是可以这么做的。这也是最近比较热门的Hash Collision DoS事件。

HashMap里重写的hashCode方法

Java代码  收藏代码
  1. public final int hashCode() {  
  2.     return (key==null   ? 0 : key.hashCode()) ^  
  3.             (value==null ? 0 : value.hashCode());  
  4.  } 
    (转载请注明出处:[url=http://www.k8764.com]博彩通[/url]

    [url=http://www.5sfd.com]e世博[/url]

posted @ 2012-04-18 19:55 夏凡 阅读(6053) | 评论 (0)编辑 收藏

[置顶]教你如何在JS端将JSON对象转化为字符串的方法

由于工作需要,要在JS端将JSON对象转化为字符串,并写到用户的COOKIE中,用来保存用户的一些个人操作习惯。便在网上搜寻了一遍,发现方法有很多,有些代码不清晰,看得乱,有些考虑不周全,生成的字符串有问题,便整合了一些好的写法,自己改进了一下。可能还是考虑得不周全,但是感觉常用的类型都考虑了,望大家多多拍砖指点!

JSON.stringify(jsonobj),本来是最简便的方法,可是存在浏览器兼容问题(仅适用于IE8+,Chrome 1+,FF 3+)。

var O2String = function (O) {
        //return JSON.stringify(jsonobj);

        var S = [];
        var J = "";
        if (Object.prototype.toString.apply(O) === '[object Array]') {
            for (var i = 0; i < O.length; i++)
                S.push(O2String(O[i]));
            J = '[' + S.join(',') + ']';
        }
        else if (Object.prototype.toString.apply(O) === '[object Date]') {
            J = "new Date(" + O.getTime() + ")";
        }
        else if (Object.prototype.toString.apply(O) === '[object RegExp]' || Object.prototype.toString.apply(O) === '[object Function]') {
            J = O.toString();
        }
        else if (Object.prototype.toString.apply(O) === '[object Object]') {
            for (var i in O) {
                O[i] = typeof (O[i]) == 'string' ? '"' + O[i] + '"' : (typeof (O[i]) === 'object' ? O2String(O[i]) : O[i]);
                S.push(i + ':' + O[i]);
            }
            J = '{' + S.join(',') + '}';
        }

        return J;
    };

/*-----------------------以下是测试代码-----------------------*/ var jsonStr = O2String( [ { "Page": "plan", "Custom": [ { "ItemName": "CustomLabel1", "ItemContent": 1, "IsItem": true, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, "ItemFunc": function () { alert("ItemFunc"); } }, { "ItemName": "CustomLabel1", "ItemContent": 1, "IsItem": true, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, "ItemFunc": function () { alert("ItemFunc"); } } ] }, { "Page": "project", "Custom": [ { "ItemName": "CustomLabel2", "ItemContent": 2, "IsItem": false, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, "ItemFunc": function () { alert("ItemFunc"); } }, { "ItemName": "CustomLabel2", "ItemContent": 2, "IsItem": false, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, "ItemFunc": function () { alert("ItemFunc"); } } ] } ] ); alert(jsonStr); var jsonObj = eval("(" + jsonStr + ")"); alert(jsonObj.length);
(转载请注明出处:[url=http://www.tdtf.org]易博网
[/url] [url=http://www.k5048.com]博彩网[/url]


posted @ 2012-04-18 19:47 夏凡 阅读(512) | 评论 (0)编辑 收藏

[置顶]你懂得在v$session 中查找locking信息吗?

现象:
系统突然报连接数过高,基本的现象就是有什么东西被锁了,导致后续的连接都在等待,那么到底是那个会话导致了阻塞那?
可以查看视图v$session ,关注以下几个字段
sid-------------------------被阻塞的进程id
status--------------------被阻塞的进程状态
COMMAND--------------被阻塞的进程执行的命令
ROW_WAIT_FILE#----被阻塞的进程对应的rowid所在的数据文件id
row_wait_block#-----row_wait_row#对应的rowid所在的表的object id
row_wait_obj#-------row_wait_row#对应的rowid所在的表的object id
row_wait_row#-----Current row being locked. This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1.但是准确的说是对应的于rowid的rownum,并非是单纯的rownum
blocking_session -----阻塞进程id
STATE-------------------被阻塞进程的状态
EVENT#----------------被阻塞进程等待的事件号
EVENT------------------被阻塞进程等待的事件
-----注意create_time是程序自动添加的
select t.sid,t.status,t.COMMAND,t.ROW_WAIT_FILE#,t.row_wait_block#,t.row_wait_obj#,t.row_wait_row#,t.blocking_session ,t.STATE,t.EVENT#,t.EVENT from temp_session t where t.BLOCKING_SESSION_STATUS='VALID' and t.create_time=to_date('2012/3/20 18:47:16','yyyy/mm/dd hh24:mi:ss');

SID  STATUS COMMAND ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_OBJ# ROW_WAIT_ROW# BLOCKING_SESSION STATE EVENT# EVENT
175 620  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
174 616  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
173 615  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
333 1050  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
179 632  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
178 629  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
332 1049  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
171 610  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
166 592  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
165 591  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention
164 589  ACTIVE 3  8 571147  77418 17  885 WAITING  239 enq: TX - row lock contention

现在可以看到885进程阻塞了好多进程,那么要获得到底是那条记录被锁定了那?

想要知道某一个表具体被锁定的是哪一行,可以利用上面这几个值,查找出被锁定行的rowid。
使用dbms_rowidb包的一个子过程(Subprograms)rowid_create
DBMS_ROWID.ROWID_CREATE (
rowid_type IN NUMBER,
object_number IN NUMBER,
relative_fno IN NUMBER,
block_number IN NUMBER,
row_number IN NUMBER)
RETURN ROWID;
其中rowid_type的取值为 0 表示生成一个restricted ROWID(pre-oracle8 format); 取值为1 表示生成一个extended ROWID.
object_number取值是dba_objects视图中的data_object_id,并不是object_id,也就是说不能用row_wait_obj#.
relative_fno取值是Relative文件号,在dba_data_files里可以查到
block_number取值是数据文件的块号,也就是v$session中的row_wait_block#的值
row_number通过rowid对应出来的rownum,也就是row_wait_row#的值。

接下来找到这些数据
rowid_type=1(11g)
object_number
selectdata_object_id from dba_objects where object_id='77418'
OBJECT_IDTT_BIGINT NOT NULLDictionary object number of the object.
DATA_OBJECT_IDTT_BIGINTIs ignored.----这是11g的文档说明,可以看出,使用object_id就可以
relative_fno=8
block_number=row_wait_block#
row_number =row_wait_row#

select * from table_name t where rowid=(
select DBMS_ROWID.ROWID_CREATE(1,77418,8,571147,17) from dual);---得到被锁定的记录;

此时查看885进程在做神马?
kill之就可以 
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]
[url=http://www.d9732.com]澳门博彩[/url])

posted @ 2012-04-18 19:45 夏凡 阅读(212) | 评论 (0)编辑 收藏

[置顶]教你如何处理隐式转换导致的负载过高的问题

现象:
突然系统报警负载过高
下面的处理步骤:
1、找到占用cpu高的进程
select tc.sql_text,tb.machine from v$process ta,v$session tb,
v$sql tc
where ta.addr=tb.PADDR
and tb.SQL_HASH_VALUE=tc.HASH_VALUE
and ta.SPID=31128
2、找到进程执行的sql






可以看到使用的了索引跳跃扫描


查看
select * from table(dbms_xplan.display_cursor('7b0908u6wx1ab'));




从这个就可以看到进行了隐式转换导致index skip scan的选择性过低,导致负载急升
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url]

posted @ 2012-04-18 19:42 夏凡 阅读(139) | 评论 (0)编辑 收藏

[置顶]有关MFC的 基础(实例)

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WinSunProc(//名字可以更改。参数类型不能变
HWND hwnd, // handle to window 窗口句柄
UINT uMsg, // message identifier 
WPARAM wParam, // first message parameter 消息参数
LPARAM lParam // second message parameter
);
/*
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
);

*/
int WINAPI WinMain(//Windows程序的入口函数
HINSTANCE hInstance, // handle to current instance 当前实例句柄
HINSTANCE hPrevInstance, // handle to previous instance 前次实例句柄
LPSTR lpCmdLine, // command line 命令行参数
int nCmdShow // show state 显示方式
)
{
/*
创建一个完整的窗口需要经过下面四个操作步骤:
1、设计一个窗口类;
2、注册窗口类;
3、创建窗口;
4、显示及更新窗口。

typedef struct _WNDCLASS { 
UINT style; //类的类型
WNDPROClpfnWndProc; //longpointfunction函数指针
int cbClsExtra; //类的附加内存
int cbWndExtra; //窗口附加内存
HANDLE hInstance; //实例号(句柄)
HICON hIcon; //图标句柄
HCURSOR hCursor; //光标句柄
HBRUSH hbrBackground; //画刷句柄
LPCTSTR lpszMenuName; //菜单的名字
LPCTSTR lpszClassName; //类的名字
} WNDCLASS; 
*/
//1、设计一个窗口类;
WNDCLASS wndcls;//窗口类
wndcls.style=CS_HREDRAW | CS_VREDRAW;//重画垂直方向、水平方向
wndcls.lpfnWndProc=WinSunProc;//函数地址
wndcls.cbClsExtra=0;//类的附加内存
wndcls.cbWndExtra=0;//窗口的附加内存
wndcls.hInstance=hInstance;//实例号
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);//图标 设置
wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);//光标 设置
wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//画刷的句柄
wndcls.lpszMenuName=NULL;//(菜单名字)
wndcls.lpszClassName="VCXTU";//注册类名(longpoint命令行参数)

//2、注册窗口类;
RegisterClass(&wndcls);//注册类

/*
HWND CreateWindow(
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu or child-window identifier
HANDLE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
*/
//3、创建窗口;
HWND hwnd;//窗口句柄
hwnd=CreateWindow(
"VCXTU",//注册类名(lpszClassName)
"湖南省湘潭市湘潭大学",//窗口名字
/*
WS_OVERLAPPEDWINDOW:
窗口风格 
WS_OVERLAPPED 层叠的 具有标题栏和边框
WS_CAPTION 有标题栏
WS_SYSMENU 带有系统菜单
WS_THICKFRAME 具有可调边框
WS_MINIMIZEBOX 具有最小化按钮
WS_MAXIMIZEBOX) 具有最大化按钮
*/
WS_OVERLAPPEDWINDOW,//窗口风格 
CW_USEDEFAULT,//窗口水平坐标(缺省的)
CW_USEDEFAULT,//窗口垂直坐标(缺省的)
600,//窗口宽度
400,//窗口高度
NULL,// 父窗口句柄(hWndParent/handle to parent or owner window)
NULL,// 菜单句柄(handle to menu or child-window identifier)
hInstance,//句柄(handle to application instance)
NULL//窗口参数(pointer to window-creation data)
);

/*
BOOL ShowWindow(
HWND hWnd, // handle to window
int nCmdShow // show state of window
);
*/
//4、显示及更新窗口。
ShowWindow(
hwnd,//窗口句柄
SW_SHOWNORMAL//显示状态 show state of window
);
UpdateWindow(hwnd);//可有可无

/*
操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序
MSG结构定义如下: 
typedef struct tagMSG { 
HWND hwnd; 
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG; 
*/
//消息循环
MSG msg;
/*
BOOL GetMessage(
LPMSG lpMsg, // address of structure with message
HWND hWnd, // handle of window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
);
*/
while(
GetMessage(
&msg,
NULL,
0,//设成0。表示对所有消息都有兴趣
0
)
)
{
/*
转换消息。可以将WM_KEYUP/WM_KEYDOWN转换为WM_CHAR消息、产生新消息并放到队列中
BOOL TranslateMessage(
CONST MSG *lpMsg // address of structure with message
);
*/
TranslateMessage(&msg);
/*
将收到的消息传到窗口的回调函数:wndcls.lpfnWndProc=WinSunProc;回调函数:WinSunProc
LONG DispatchMessage(
CONST MSG *lpmsg // pointer to structure with message
);
*/
DispatchMessage(&msg);
}
return 0;
}

LRESULT CALLBACK WinSunProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
case WM_CHAR://表示按下了某个字符按键
char szChar[20];
sprintf(szChar,"char is %d",wParam);//格式化消息。WM_CHAR中的wParam参数
/*
int MessageBox(
HWND hWnd, //拥有消息的父窗口 handle of owner window
LPCTSTR lpText, //文本 address of text in message box
LPCTSTR lpCaption, //标题 address of title of message box
UINT uType //消息框的风格 style of message box
);
*/
MessageBox(
hwnd,
szChar,
"湘潭大学",//标题
MB_OKCANCEL//MB_YESNO//消息框的风格
);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"鼠标左键点击了","湘潭大学",MB_OKCANCEL);
HDC hdc;//句柄 handle to device context
/*
HDC GetDC(
HWND hWnd // handle to a window
);
*/
hdc=GetDC(hwnd);
/*
BOOL TextOut(
HDC hdc, // handle to device context
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString // number of characters in string
); 
*/
TextOut(hdc,0,50,"湖南省湘潭市湘潭大学1",strlen("湖南省湘潭市湘潭大学1"));
ReleaseDC(hwnd,hdc);//释放DC
break;
case WM_PAINT://窗口重绘
HDC hDC;
PAINTSTRUCT ps;
/*
HDC BeginPaint(
HWND hwnd, // handle to window
LPPAINTSTRUCT lpPaint
// pointer to structure for paint information
);
*/
hDC=BeginPaint(hwnd,&ps);//只能在WM_PAINT里面使用
TextOut(hDC,0,0,"湖南省湘潭市湘潭大学hDC",strlen("湖南省湘潭市湘潭大学hDC"));
EndPaint(hwnd,&ps);//只能在WM_PAINT里面使用
break;
case WM_CLOSE://关闭窗口时响应
if(IDYES==MessageBox(hwnd,"是否真的结束?","湘潭大学",MB_YESNO))
{
DestroyWindow(hwnd);//销掉hwnd窗口 还会发送 WM_DESTROY、WM_NCDESTROY 消息
}
break;
case WM_DESTROY:
PostQuitMessage(0);//退出程序
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
(转载请注明出处:[url=http://www.live588.org]淘金盈[/url]

[url=http://www.10086money.com]时尚资讯[/url]

posted @ 2012-04-18 19:39 夏凡 阅读(306) | 评论 (0)编辑 收藏

[置顶]教你如何获取绑定变量的各种方法

1、查询v$sql视图
selectsql_id, sql_text, bind_data,HASH_VALUE from v$sql where sql_text Like '%select * from test where id1%';
它的记录频率受_cursor_bind_capture_interval 隐含参数控制,默认值900,表示每900秒记录一次绑定值,可以通过alter system set "_cursor_bind_capture_interval"=10;

此时查询到的data值得形式是这样的:BEDA0B2002004F8482D10065FFFF0F00000000000000000000C0021602C102C0021602C102F0018003691532303132303431313032504F443834363135313635F0018003691532303132303431313032504F443834363135313730F0018003691532303132303431313032504F443834363135313731F0018003691532303132303431313032504F443834363135313734F0018003691532303132303431313032504F443834363135313735F0018003691532303132303431313032504F443834363135313739F0018003691532303132303431313032504F443834363135313830F0018003691532303132303431313032504F443834363135313833F0018003691532303132303431313032504F443834363135313834F0018003691532303132303431313032504F443834363135313838F0018003691532303132303431313032504F443834363135313839F0018003691532303132303431313032504F443834363135313933F0018003691532303132303431313032504F443834363135313934F0018003691532303132303431313032504F443834363135313937F0018003691532303132303431313032504F443834363135313938F0018003691532303132303431313032504F443834363135323033F0018003691532303132303431313032504F443834363135323034F0018003691532303132303431313032504F443834363135323037
这样肯定是没法看懂的

需哟进行转换
select dbms_sqltune.extract_binds(bind_data) bind from v$sql WHERE SQL_TEXT LIKE '%FROM TEST11%';


2、查询SELECT VALUE_STRING FROM V$SQL_BIND_CAPTURE WHERE SQL_ID='abhf6n1xqgrr0';
通过v$sql_bind_capture视图,可以查看绑定变量,但是这个视图不太给力,只能捕获最后一次记录的绑定变量值。

而且两次捕获的间隔有一个隐含参数控制。默认是900秒,才会重新开始捕获。在900内,绑定变量值的改变不会反应在这个视图中。

10G以后可以通过如下方法查看AWR报告里记录的SQL的绑定变量值。

select snap_id, name, position, value_string,last_captured,WAS_CAPTUREDfrom dba_hist_sqlbind where sql_id = '576c1s91gua19' and snap_id='20433';

----------SNAP_ID就是AWR报告的快照ID

----------name,绑定变量的名称

----------position,绑定值在SQL语句中的位置,以123进行标注

---------value_string,就是绑定变量值

---------,last_captured,最后捕获到的时间

---------WAS_CAPTURED,是否绑定被捕获,where子句前面的绑定不进行捕获。

dba_hist_sqlbind视图强大的地方在于,它记录了每个AWR报告里的SQL的绑定变量值,当然这个绑定变量值也是AWR生成的时候从v$sql_bind_capture采样获得的。

通过这个视图,我们能够获得比较多的绑定变量值,对于我们排查问题,这些值一般足够了。

还有一个需要注意的地方是,这两个视图中记录的绑定变量只对where条件后面的绑定进行捕获,这点需要使用的时候注意。

3、查询dba_hist_sqlbind VALUE_STRING列
DBA_HIST_SQLBIND是视图V$SQL_BIND_CAPTURE历史快照

4、查询wrh$_sqlstat
select dbms_sqltune.extract_bind(bind_data, 1).value_string
from wrh$_sqlstat
where sql_id = '88dz0k2qvg876'----根据绑定变量的多少增加dbms_sqltune.extract_bind(bind_data, 2).value_string等 
(转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url]
[url=http://www.9gds.com]易博网[/url])

posted @ 2012-04-18 16:53 夏凡 阅读(393) | 评论 (0)编辑 收藏

2012年4月19日

教你如何将普通表转换为分区表

需求描述:
一个表已经上线,但是上线之后发现该表的数据量很大,而且会删除历史数据,该表上要建立多个唯一索引,现在的问题就是在建表的时候是建立了一个普通表,现在需要将普通表转化为分区表,并尽量减少对应用的影响
1、使用ctas的方式来建立
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)----原表


---建立分区表:
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
as
select * from t1;----此时应用还是不断的往t1表中插入数据-


alter table t1_new add constraints pk_t1_new primary key (id) using tablespace local index_tablespace;----建立本地索引为了删除历史数据
/alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


但是应用还在outer_id上建立唯一索引
create unique index IDX_t1_new_2 on t1_new (OUTER_ID) LOCAL ;
此时报


ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集
原来oracle不支持在分区表上创建PK主键时主键列不包含分区列,创建另外的约束(unique)也不可以。
为了解决这个问题,两种方法
1、将分区键加到唯一索引里面
2、将local索引变为global索引----此时当进行历史数据删除的时候会导致索引失效
权衡之后在outer_id上建立普通索引




alter table t1 rename to t1_bak;
alter table t1_new rename to t1;
在进行ctas之后需要进行数据完整新检查,而且在进行rename的时候会导致应用连接失效(也有可能在进行alter的时候获取不到表锁而失败)---适用于修改不很频繁的表


2、使用交换分区的方式
----原表
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)
alter table t1 add constraints pk_t1 primary key(id) ;


新表
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


ALTER TABLE t1_new EXCHANGE PARTITION p_t1_new WITH TABLE t1 without validation;----要不要加上without validation(加上的话就是不验证数据是否有效,直接全部放在p_t1_new分区中)
然后进行rename操作


优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。
不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。
适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。


3、在线重定义
----原表
create table t1
(
ID VARCHAR2(60) not null,
a VARCHAR2(60) not null,
b VARCHAR2(60) not null,
create_time TIMESTAMP(6) not null,
d NUMBER(2) not null,
e VARCHAR2(400) not null,
OUTER_ID VARCHAR2(100)
)
alter table t1 add constraints pk_t1 primary key(id) ;


新表
create table t1_new
(
ID_1 ,
a ,
b ,
create_time ,
d ,
e ,
OUTER_ID 
)partition by range (ID_1)
(
partition p_t1_new values less than ('201204'),
partition p_t2_new values less than ('201205'))
alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;


EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T1', DBMS_REDEFINITION.CONS_USE_PK);

EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T1', 'T1_NEW',DBMS_REDEFINITION.CONS_USE_PK);
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]

[url=http://www.d9732.com]澳门博彩[/url]

posted @ 2012-04-19 15:31 夏凡 阅读(1135) | 评论 (0)编辑 收藏

聊聊关于请求重定向与请求发的比较

尽管httpservletresponse.sendredirect方法和requestdispatcher.forward方法都可以让浏览器获得另外一个url所指向的资源,但两者的内部运行机制有着很大的区别。下面是httpservletresponse.sendredirect方法实现的请求重定向与requestdispatcher.forward方法实现的请求转发的总结比较:

(1)requestdispatcher.forward方法只能将请求转发给同一个web应用中的组件;而httpservletresponse.sendredirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对url重定向到其他站点的资源。如果传递给httpservletresponse.sendredirect 方法的相对url以“/”开头,它是相对于整个web站点的根目录;如果创建requestdispatcher对象时指定的相对url以“/”开头,它是相对于当前web应用程序的根目录。

(2)调用httpservletresponse.sendredirect方法重定向的访问过程结束后,浏览器地址栏中显示的url会发生改变,由初始的url地址变成重定向的目标url;而调用requestdispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的url地址不变。

(3)httpservletresponse.sendredirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个url的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。requestdispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。

(4)requestdispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而httpservletresponse.sendredirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个web应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用httpservletrequest.setattribute方法传递预处理结果,那就应该使用requestdispatcher.forward方法。不同web应用程序之间的重定向,特别是要重定向到另外一个web站点上的资源的情况,都应该使用httpservletresponse.sendredirect方法。

(5)无论是requestdispatcher.forward方法,还是httpservletresponse.sendredirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。  
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url]

posted @ 2012-04-19 14:34 夏凡 阅读(216) | 评论 (0)编辑 收藏

简单介绍java中Runtime类和Process类

在java.lang包当中定义了一个Runtime类,在java中对于Runtime类的定义如下:
public class Runtime
extends Object
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。
根据上面的话,我们知道对于每一个java程序来说都只有一个Runtime类实例,而且不能由用户创建一个Runtime实例,既然不能创建那么这个类的实例的作用是什么呢?它提供了应用程序和应用程序正在运行的环境的一个接口。Runtime不能由我们创建,我们可以通过Runtime类的一个静态方法,得到一个Runtime类的实例。获取了这个实例之后我们就可以获取java虚拟机的自由内存、也可以获取这个java虚拟机的总的内存等(具体的方法可以参照java帮助文档Runtime类的方法学习),也就是说这个类提供了应用程序了环境的接口。下面我们举一个例子程序:
Runtime rt=Runtime.getRuntime();
System.out.println(rt.freeMemory());
System.out.println(rt.totalMemory());//结果返回的是数字
Runtime类还有一个好处就是可以执行一个外部的程序,可以调用Runtime类的exec()方法传入一个命令(exec()方法有几个重载的方法,可以自己学习),创建一个子进程,结果返货一个Process类的实例,通过这个实例我们可以管理创建的子进程。对于Process类在java帮助文档中描述如下:
public abstract class Process
extends Object
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

public abstract class Process
extends Object
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
下面我们接着上面的代码继续写:
try{
rt.exec("notepad");}
catch(Exception e){
e.printStackTrace;}//在使用exec()方法的时候会抛出一个异常,我们需要捕获
这段代码,是运行在windows上的,它调用了windows系统的记事本程序。举一反三我们同样可以用这个方法去编译java的文件,只是传入的参数是“javac ***.java”。
对于Process类的实例主要作用是创建一个可以管理的进程,并对它进行管理。Process类还有几个方法分别是destroy() 杀掉子进程、exitValue()返回子进程的出口值、getErrorStream()获取子进程的错误流,错误流获得由该 Process 对象表示的进程的错误输出流传送的数据,还有获取输入流输出流请读者自己参照java帮助文档学习。
这是自己在接触Runtime类和Process类的时候学到的一些东西,分享出来希望对大家有用,大家看见了若是有不对的地方,请指出来。 
(转载请注明出处:[url=http://www.live588.org]淘金盈[/url]
[url=http://www.10086money.com]时尚资讯[/url])

posted @ 2012-04-19 10:21 夏凡 阅读(818) | 评论 (0)编辑 收藏

关于Java多线程1—程序、进程、线程的一些比较

许多人对于程序、进程、线程这几个概念许多人都分的不是很清楚,下面我们就简单的介绍一下它们的区别。

程序是计算机指令的集合,它以文件的形式存储在磁盘上。程序是通常我们所写好的存储于计算机上没有执行的指令的集合,通俗的讲就是我们自己写的代码。我们写的代码不可能只是为了存储吧,必须运行才不会浪费我们的辛苦,等到我们将我们的代码运行了,就产生了进程。

进程:是一个程序在其自身的地址空间中的一次执行活动。通常的程序是不能并发执行的。为了使程序能够独立运行,应该为之配置一些进程控制块,即PCB;而由程序段,相关数据段和PCB三部分构成了进程实体。通常我们并不区分进程和进程实体,基本上就代表同一事物。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。

20世纪60年代人们提出了进程的概念,在OS中一直都是以进程作为能独立运行和拥有资源的基本单位。但是进程间的切换比较麻烦费时,所以在20世纪80年代人们为了提高系统内程序并发执行的程度,进一步提高系统的吞吐量,提出了比进程更小的能独立运行的基本单位。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。一个进程可以同时拥有一个或者多个线程,这几个线程共享同样的数据。

现在的CPU几乎都是多核的了,这样多线程的程序,运行起来就更加流畅。下面我们通过图片来比较一下单线程和多线程:


这个就好比我们算一道数学题(2+3)*(5-3),如果我们使用左边的单线程,只能是先算2+3然后算5-3,最后结果相加。但是如果我们使用右边的多线程,我们可以同时对2+3和5-3进行运算,然后再对最后的结果相加。我想哪个运行的比较快就不用说了,另外多线程在图像处理,多用户通信等方面用户都很多。

可能读者会说如果我们用的是单CPU的PC那么他们就差别不大了,但是现在的事实是现在的PC基本都是多核了,所以多线程是为了我们更好的将程序移植到多核的CPU上。还有一点就是对于线程的切换,比进程的切换速度快的多,多线程更好的发挥CPU的效率。

写的不好,如果哪里错了希望大家指出。希望对你有帮助。
(转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url]

[url=http://www.9gds.com]易博网[/url])

posted @ 2012-04-19 10:19 夏凡 阅读(276) | 评论 (0)编辑 收藏

java中的多态,多态的例子

当面临一个问题,有多种实现算途径的时候,要想到java中的核心:多态。


多态的思想:

概括地讲,在运用父类引用指向子类对象的情况下,基本上就用到了多态了。


最简单的多态应该是继承:

public class Tank {
public void move() {
System.out.println("I am father");
}
}


public class Tank2 extends Tank{
@Override
public void move(){
System.out.println("I am child a");
}

public class Client {
public static void main(String[] args) {
Tank t2 = new Tank2(); ///父类引用指向了子类对象
t2.move(); ///父类中的move方法,但实际具体的实现是tank2对象对move的实现。

}

}

接口和抽象类的例子:


对于抽象类和接口,有许多类实现这个接口(或者继承这个抽象类)。
在调用的时候,用父类引用指向子类对象的方法。然后,调用对象的方法,编译器就会自动根据这个对象实际属于哪个实现类,
来调出这个类对于接口或者抽象类的具体实现。

例:
public class Address {
private String name;
public Address(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

定义基类(抽象类):
public abstract class Vehicle {
abstract void go(Address address);
}

Car对于基类的实现:
public class Car extends Vehicle{
@Override
public void go(Address address){
System.out.println("Car to " + address.getName());
}
}

Plane对于基类的实现:
public class Plane extends Vehicle{
@Override
void go(Address address) {
System.out.println("Plane to " + address.getName());
}
}


Driver中多态:
public void drive(Vehicle v){ ///多态,父类引用指向子类对象,实际传过来的是抽象类Vehicle的子类,或者实现类,然后编译器会根据具体实现类,来找实现方法。
v.go(new Address("杭州(abstract)")); ///此方法在具体的实现中被重写
}

Test:
public static void main(String[] args) {
Driver d = new Driver();
d.drive(new Plane()); //实际是Plane对象,则编译器就会找到Plane中,对go的实现
d.drive(new Car()); //实际是Car对象,则编译器就会找到Plane中,对go的实现
}

输出结果:
Plane to 杭州(abstract)
Car to 杭州(abstract)

事实上,这就是多态所起的作用,可以实现控制反转这在大量的J2EE轻量级框架中被用到,比如Spring的依赖注射机制。
(通过注入不同的bean,来得到不同的实现类)

接口与抽象类的区别:

有个概念,但还没有想到具体实现。
对于一些共用的,已经有实现了,可以设计成接口。

上面是抽象类,下面把它转化为接口:

IVehicle.java
public interface IVehicle {
public void go(Address address);
}

CarImpl.java
public class CarImpl implements IVehicle{
public void go(Address address) {
System.out.println("CarImpl to " +address.getName());
}
}

PlameImpl.java
public class PlaneImpl implements IVehicle{
public void go(Address address) {
System.out.println("PlaneImpl to " + address.getName());
}
}

Driver.java
////多态之接口
public void driveI(IVehicle v){
v.go(new Address("杭州(interface)"));
}

Test.java
////用接口实现
d.driveI(new PlaneImpl());
d.driveI(new PlaneImpl());

打印结果:
PlaneImpl to 杭州(interface)
PlaneImpl to 杭州(interface)


多态的三要素:1.继承 2.重写 3.父类引用指向子类对象

以上就是我目前学习中的总结,如有不足之处,还望多多赐教。
(转载请注明出处:[url=http://www.k8764.com]博彩通[/url]

[url=http://www.5sfd.com]e世博[/url])

posted @ 2012-04-19 10:15 夏凡 阅读(1140) | 评论 (0)编辑 收藏

如何使用java读取Properties文件来改变实现类

用java读取Properties文件来改变实现类的Demo:


public abstract class Vehicle {
public abstract void run();
}


public class Car extends Vehicle{
public void run(){
System.out.println("with Car");
}
}


public class Broom extends Vehicle {
@Override
public void run() {
System.out.println("Broom");
}
}


test.properties 中:
VehicleType=abstractfactory.step4properties.Broom
注意:该文件要放在src目录下,且等号两边不可有空格




import java.util.Properties;
public class Test {
public static void main(String[] args) throws Exception{
Properties pros = new Properties();
///配置文件编译之后放在bin目录下
//每个class的类,都会被当作Class对象。getClassLoader:拿到了装载这个Class的装载器
///把它当作一个流读进来,默认路径是根目录。读出来之后,把它转化为一个properties对象,然后,等号左边的就是key,等号右边的就是value
pros.load(Test.class.getClassLoader().getResourceAsStream("abstractfactory/step4properties/spring.properties"));

String vehicleTypeName = pros.getProperty("VehicleType");
System.out.println(vehicleTypeName);


///现在,得到的字符串,我们想把字符串代表的类,产生一个对象,用到反射
///Class.forName把字符串所代表的表装到内存,newInstance:生成对象,得到的是个Object
Vehicle v = (Vehicle)Class.forName(vehicleTypeName).newInstance();
v.run();
//只要改变test.properties中的VehicleType=factory.step4Spring.Broom,即可实现改变实现类的功能。
}
}
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]
[url=http://www.d9732.com]澳门博彩[/url])

posted @ 2012-04-19 10:05 夏凡 阅读(924) | 评论 (0)编辑 收藏

教你关于JSP连接MYSQL5的中文问题解决方法

用JAVA/JSP做开发很久了,也见过许多朋友做过,有很大一部分用的是MYSQL的数据库,现在MYSQL数据库版本5.0及以上的都已经被用的很广泛了,但一直有一个问题,使刚入门的朋友费劲心思.就是JSP连接MYSQL5数据库的时候的一些中文问题.于是网络上也出现了很多相关的帖子.由些大家对MYSQL5数据库的配制文件MY.INI也有了些了解.甚至一些朋友就直接问:你们的MYSQL是什么编码的?你们的TOMCAT是什么样的编码,可能不是很规范的问法,但说明了编码问题的确影响了大家的使用.

下面的讲解是在MYSQL5.0.18,TOMCAT5.0.28,驱动为mysql-connector-java-3.2.0-alpha-bin.jar及以上版本的情况下测试的

JSP连接数据库的乱码问题,分两部分来看

1 数据库中是不是乱码?

我们需要保证数据库保存的不是"?????"形式的乱码,如何保证呢?

我们在管理MYSQL数据库的时候,需要用一个客户端,无论你用MYSQL-FRONT,EMS SQL Manager for MySQL,还是MYSQL命令行,这些都是客户端,也是程序连接了数据库,我们现在用客户端EMS SQL Manager for MySQL连接数据库,连接的时候一定要设置客户端字符集为GBK或者GB2312,这样你才能知道数据库里面是不是乱码.这一编码设置很重要,不然,就算数据库里是中文,你看到的还是乱码

这样连接后,我们看下我们做测试的表格,里面的汉字就是正常的,这个时候也可以直接在上面的记录中进入中文的修改

若这里没有选择编码的话,一般默认的就是UTF8的了,连接后再看这个表格,就会出现乱码

而这个时候就会出现不能插入中文的问题,若您插入中文的话,就会出现下列错误

这个时候大家什么不要误解,不是不能插入中文,也不是你插入的字符太长,

更改下连接编码就OK了.下面是这个表格的SQL语句

CREATE TABLE `test` (
`name` varchar(100) default NULL,
`adesc` varchar(100) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

二.程序连接数据时,也要设置好连接时候的编码,JSP连接MYSQL数据库时候,有个URL参数,jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8,在这里需要设置成UTF-8,

下面是连接数据库的程序代码

<%@ page contentType="text/html;charset=GB2312" language="java"%>
<%@ page import="java.io.*" %> 
<%@ page import="java.util.*" %>
<%@ page import="java.sql.*" %>

<%
out.println("您的数据库某表格中的内容如下<br>");
try {
Class.forName("com.mysql.jdbc.Driver").newInstance(); 
String url ="jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8";
//testDB为你的数据库名 
Connection conn= DriverManager.getConnection(url); 
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql="select * from test";

ResultSet rs=stmt.executeQuery(sql); 
while(rs.next()) {
out.println("第一个字段内容:<font color=red>"+rs.getString(1)+"</font> 第二个字段内容:<font color=red>"+rs.getString(2)+"</font><br>");
}
out.print("数据库操作成功,恭喜你");

sql = "insert into test (name,adesc) values ('中文','汉字')";
stmt.execute(sql);


rs.close(); 
stmt.close(); 
conn.close(); 
}
catch(Exception e){
System.out.println("数据库连接不成功"+e.toString());
}
%>

上面的经验是经过多次尝试总结出来的,不管是MYSQL的客户端还是程序连接MYSQL数据库,在本质上都是程序连接数据库,可以自己在本地多试验下,有时候有可能是驱动太旧.
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url]

posted @ 2012-04-19 09:58 夏凡 阅读(211) | 评论 (0)编辑 收藏

你懂得如何用QTP录制鼠标右键点击事件吗

qtp录制鼠标右键单击事件要通过模拟键盘操作来实现

step 1,修改replaytype为2,一般情况默认设置是1的。(1 – 使用浏览器事件运行鼠标操作。 2 – 使用鼠标运行鼠标操作)
setting.webpackage(”replaytype”) = 2

step 2,鼠标右键单击事件
(附:click的事件有三种 micleftbtn 0 鼠标左键。 micrightbtn 1 鼠标右键。 micmiddlebtn 2 鼠标中键)
browser(”支付宝 – 网上支付 安全快速!”).page(”支付宝 – 网上支付 安全快速!”).link(”返回我要付款”).click , , micrightbtn

step 3,点击右键弹出的菜单(采用键盘事件来模拟)
set wshshell = createobject(”wscript.shell”)
wshshell.sendkeys “{down}” //键盘向下的箭头
wshshell.sendkeys “{down}”
wshshell.sendkeys “{enter}” //回车键

step 4,修改replaytype为1(使用浏览器事件运行鼠标操作)
setting.webpackage(”replaytype”) = 1

good to go now. 
(转载请注明出处:[url=http://www.live588.org]淘金盈[/url]
[url=http://www.10086money.com]时尚资讯[/url])

posted @ 2012-04-19 09:51 夏凡 阅读(446) | 评论 (0)编辑 收藏

通过jquery 获取父窗口的元素 父窗口 子窗口的方法

     摘要: $("#父窗口元素ID",window.parent.document); 对应javascript版本为window.parent.document.getElementByIdx_x("父窗口元素ID"); 取父窗口的元素方法:$(selector, window.parent.document); 那么你取父窗口的父窗口的元素就可以用:$(selector, w...  阅读全文

posted @ 2012-04-19 09:49 夏凡 阅读(478) | 评论 (0)编辑 收藏

教你使用C# 实现文件锁

     摘要: C#代码  using System;  using System.Collections.Generic;  using System.ComponentModel;  using System.Data;  using System.Drawin...  阅读全文

posted @ 2012-04-19 09:43 夏凡 阅读(1076) | 评论 (0)编辑 收藏