import java.io.*; public class GetUserInput { public static void main (String[] args) { System.out.print("Enter your name and press Enter: "); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String name = null; try { name = br.readLine(); } catch (IOException e) { System.out.println("Error!"); System.exit(1); } System.out.println("Your name is " + name); } } |
August 10, 2010
Java : get user input
August 3, 2010
JAVA进阶:提高SQL性能的几种方法
1, 从 INSERT 返回 IDENTITY
SELECT @@IDENTITY
2, 内嵌视图与临时表
临时表 – 在 tempdb 中的临时表会导致查询进行大量 I/O 操作和磁盘访问,临时表会消耗大量资源。
内嵌视图 -使用内嵌视图取代临时表。内嵌视图只是一个可以联接到 FROM 子句中的查询。如果只需要将数据联接到其他查询,则可以试试使用内嵌视图,以节省资源。
3, 避免 LEFT JOIN 和 NULL
LEFT JOIN 消耗的资源非常之多,因为它们包含与 NULL(不存在)数据匹配的数据。在某些情况下,这是不可避免的,但是代价可能非常高。LEFT JOIN 比 INNER JOIN 消耗资源更多,所以如果您可以重新编写查询以使得该查询不使用任何 LEFT JOIN,则会得到非常可观的回报。
加快使用 LEFT JOIN 的查询速度的一项技术涉及创建一个 TABLE 数据类型,插入第一个表(LEFT JOIN 左侧的表)中的所有行,然后使用第二个表中的值更新 TABLE 数据类型。此技术是一个两步的过程,但与标准的 LEFT JOIN 相比,可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间,直到获得用于您的应用程序的执行性能最佳的查询。
DECLARE @tblMonths TABLE (sMonth VARCHAR(7))
4, 灵活使用笛卡尔乘积
对于此技巧,我将进行非常详细的介绍,并提倡在某些情况下使用笛卡尔乘积。出于某些原因,笛卡尔乘积 (CROSS JOIN) 遭到了很多谴责,开发人员通常会被警告根本就不要使用它们。在许多情况下,它们消耗的资源太多,从而无法高效使用。但是像 SQL 中的任何工具一样,如果正确使用,它们也会很有价值。
其中一段示例代码,值得效仿:
– 笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘,生成一个行集合,其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此,笛卡尔乘积会向表 @tblFinal 返回 12(所有月份)*81(所有客户)=972 行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新 @tblFinal 表,以及选择最终的行集。
DECLARE @tblMonths TABLE (sMonth VARCHAR(7))
DECLARE @tblCustomers TABLE ( CustomerID CHAR(10),
CompanyName VARCHAR(50),
ContactName VARCHAR(50))
DECLARE @tblFinal TABLE ( sMonth VARCHAR(7),
CustomerID CHAR(10),
CompanyName VARCHAR(50),
ContactName VARCHAR(50),
mSales MONEY)
DECLARE @dtStartDate DATETIME,
August 2, 2010
去掉log4j 的warning
最近在作项目的时候,用到了 HttpClient,用它向 HTTP server 发送请求并处理返回的页面数据。
我的应用类间接调用 HttpClient。在运行的时候,程序打印出了如下警告信息:
log4j:WARN No appenders could be found for logger
log4j:WARN Please initialize the log4j system properly.
而我不想打印任何不属于我程序自己的消息。怎样去掉这些警告呢?
原因:
HttpClient 使用 org.apache.commons.logging 作为日志处理接口,该接口可以集成多种日志模块,如 log4j,或它自带的 SimpleLog。HttpClient 应该是默认使用log4j 作为它的日志处理模块,因为log4j 是最流行的日志处理模块。
如果不在程序运行环境中设置 log4j.properties 文件,log4j 就会报上述警告了。
解决方法:
1 - 如果应用程序需要 HttpClient 通过 log4j 打印日志的话,就在应用程序运行路径下加上log4j.properties 文件,具体内容网上很多文章都说过了。
2 - 如果应用程序不需要HttpClient 通过 log4j 打印日志,例如我的应用程序,则可以在自己应用程序的开始之处,利用如下语句直接去掉日志:
System.setProperty( “org.apache.commons.logging.Log”, “org.apache.commons.logging.impl.NoOpLog” );
重新运行程序,发现上述那两行 log4j 的警告已经没有了。
Post in HtmlUnit
from : http://colinhowe.wordpress.com/2009/06/24/htmlunit-how-to-do-a-post/
final WebClient webClient = new WebClient();
// Instead of requesting the page directly we create a WebRequestSettings object
WebRequestSettings requestSettings = new WebRequestSettings(
new URL("URL GOES HERE"), HttpMethod.POST);
// Then we set the request parameters
requestSettings.setRequestParameters(new ArrayList());
requestSettings.getRequestParameters().add(new NameValuePair("name of value to post", "value"));
// Finally, we can get the page
HtmlPage page = webClient.getPage(requestSettings);
Quite a lot of work for a simple… I imagine it won’t be hard to wrap this up into a neat POST method.
Ahmed Ashour says:
Hi,
Thanks for your post.
Yes, it is not easy, but also real browsers don’t provide a way for you to direct post a request, you have to go to a page, and click a link, then it will post.
HtmlUnit main usage is simulating real browsers usage, and customized actions would need the user to dig into the API a little.
LCamel says:
If HtmlUnit can’t correctly generate a form with JavaScript, we may still need to do a direct POST…
(Please remove my previous comment, thanks.)
July 28, 2010
July 26, 2010
java static block 的用法
public class StaticBlock { static { // this is a static block data = (int)(Math.random()*100); } static int data; public static void main(String[] argv) { System.out.println(data); } }
July 21, 2010
java timer class
import java.io.IOException;
import java.util.Timer;
public class TimerTest {
public static void main(String[] args){
Timer timer = new Timer();
timer.schedule(new MyTask(), 1000, 2000);//在1秒后执行此任务,每次间隔2秒,如果传递一个Data参数,就可以在某个固定的时间执行这个任务.
while(true){//这个是用来停止此任务的,否则就一直循环执行此任务了
try {
int ch = System.in.read();
if(ch-’c'==0){
timer.cancel();//使用这个方法退出任务
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

static class MyTask extends java.util.TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(“________”);
}
}



}


July 7, 2010
java多线程的两点误区
在使用java线程的时候,特别是初学者总会有几点很常见的误区,下面以以下代码为例:
线程类:
package threadtest1;
public class ReturnThreadInfo extends Thread {
private String str;
public ReturnThreadInfo() {
this.str = “Hello”;
}
public void run(){
try{
this.str = “Hello World!”;
}catch(Exception ex){
}
}
/*返回线程信息:str变量的值*/
public String getThreadInfo(){
return this.str;
}
}
主类:
package threadtest1;
public class Main extends Thread {
public Main() {
}
public static void main(String[] args) {
ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();
returnThreadInfo.start();
System.out.println(returnThreadInfo.getThreadInfo());
}
}
大家可以看到这个程序主要功能是返回线程returnThreadInfo对象的变量str的值并输出,那么str的值到底是什么,一些人可能会认为
是”Hello world!”或是null,其实如果大家运行下就会知道输出的str的值实际是”Hello”。为什么呢?其实认为输出结果是”Hello world”或是
null的人存在着两个比较常见的误区:
1、误区一:认为returnThreadInfo对象中的run方法一定在主类的System.out.println(returnThreadInfo.getThreadInfo())之间运行。
这是比较常见的一个误区,稍微了解一些java编译原理的人应该清楚,java源文件的代码编译是自上而下的,也就是处在同一文件上面的代
码会在下面的代码之间被编译和运行。所以很多人认为returnThreadInfo.start()先被运行,returnThreadInfo线程被启动,然后run()方法被
调用,str被赋值:”hello world!”,然后线程结束并返回到主类,最后调用System.out.println(returnThreadInfo.getThreadInfo())将str
的值输出就是”Hello world!”。
如果returnThreadInfo不是一个线程而是一个普通类的对象,那么输出的结果是”Hello world”,但是正因为returnThreadInfo是一个线程
,所以run方法并不一定在System.out.println(returnThreadInfo.getThreadInfo())之前运行。因为实际上主类Main在运行时也是一个线程,
当调用returnThreadInfo.start()方法来启动returnThreadInfo线程后,此时系统中运行的实际上就是Main和returnThreadInfo两个线程,那
么这两个线程就会竞争CPU,谁先抢到CPU的控制权,谁就会先运行(实际上线程谁能优先抢到CPU运行时间是靠优先级来决定的,优先级可以通
过线程的setPriority(int newPriority)来设置,newPriority的取值是1-10,newPriority值越大,线程的优先级就越高,优先强占CPU的几率
就越大。线程默认的优先级是5)。由于Main和returnThreadInfo的优先级都默认为5,所以它们争抢CPU的几率是相同的。又因为Main线程实际
上是比returnThreadInfo线程先启动的,所以在这个程序中,Main的System.out.println(returnThreadInfo.getThreadInfo())反而比
returnThreadInfo的run方法更早运行,所以输出的str值还是初始的”Hello”。
2、误区二:认为线程运行完毕后,线程消亡的同时,线程对象也会一并被回收。
下面对ReturnThreadInfo类的源代码进行修改,将ReturnThreadInfo线程的优先级设置为10:
public ReturnThreadInfo() {
this.str = “Hello”;
this.setPriority(10);
}
这样returnThreadInfo线程的run()方法就会在Main类的System.out.println(returnThreadInfo.getThreadInfo())语句之前被运行。因此
有很多人会认为当returnThreadInfo线程的run()方法运行完毕并返回后,线程就会死亡,那么Main类的最后一句System.out.println
(returnThreadInfo.getThreadInfo())就会出问题,等于调用了已经不存在的对象:returnThreadInfo。
实际上这存在着很大的一个误区,线程的死亡并不意味着线程对象的销毁和回收。线程的死亡指的是当线程的run方法结束后,该线程就无
法被重用和启动,但它的对象还存在并且它的属性和方法还一样可以被使用,因此System.out.println(returnThreadInfo.getThreadInfo())
输出的并不是NULL而是”Hello World!”,只有当整个应用程序都结束后,returnThreadInfo对象才会被销毁和回收。