日出星辰

2011年9月5日 #

从需求开发会议谈起

今天项目组进行了一个小时的需求讨论,由于刚进入项目组不久,对系统了解不多,几乎没有发言一直在旁听。

此次会议得出一点心得:系统开发中最重要的就是解决方案的敲定,解决方案选择对的话,就算没有达到事半功倍的效果,开发人员开发起来也能轻松很多。

怎么才能产生一个好的解决方案,这就与对系统、需求、技术的掌握程度了,程度越高考虑事情越周全、解决方案越有效。

由此也可以得出,企业在选择员工时应该看重分析问题、解决问题的能力,而不是技术能力。当然了,技术能力一般,解决问题能力可能也不是多好。

一个好的程序员:技术能力+解决问题能力(思维逻辑),所以技术是基础、必备的,技术上要每天都有收获,思维方式要时刻注意培养,不仅仅是解决开发问题时注意,日常生活同样使用。

posted @ 2011-10-21 23:19 日出星辰 阅读(143) | 评论 (0)编辑 收藏

你的成功在于你每天养成的习惯

要成功,就马上准备有所付出吧!这就是每天你应该养成的习惯。 
1、不说“不可能”; 
2、凡事第一反应: 找方法,不找借口; 
3、遇到挫折对自己说声:太好了,机会来了! 
4、不说消极的话,不落入消极的情绪,一旦发生立即正面处理; 
5、凡事先订立目标; 
6、行动前,预先做计划; 
7、工作时间,每一分、每一秒做有利于生产的事情; 
8、随时用零碎的时间做零碎的事情; 
9、守时; 
10、写点日记,不要太依靠记忆; 
11、随时记录想到的灵感; 
12、把重要的观念、方法写下来,随时提示自己; 
13、走路比平时快30%,肢体语言健康有力,不懒散、萎靡; 
14、每天出门照镜子,给自己一个自信的微笑; 
15、每天自我反省一次; 
16、每天坚持一次运动; 
17、听心跳一分钟,在做重要的事情,疲劳时,紧张时,烦躁时。。。。 
18、开会做前排; 
19、微笑; 
20、用心倾听,不打断对方的话; 
21、说话有力,感觉自己的声音能产生感染力的磁场; 
22、说话之前,先考虑一下对方的感觉; 
23、每天有意识赞美别人三次以上; 
24、即使表示感谢,如果别人帮助了你的话; 
25、控制住不要让自己作出为自己辩护的第一反应; 
26、不用训斥、指责的口吻与别人说话; 
27、每天做一件”分外事“; 
28、不关任何方面,每天必须至少做一次”进步一点点“,并且有意识的提高; 
29、每天提前15分上班,推迟30分下班; 
30、每天下班前5分钟做一下今天的整理工作; 
31、定期存钱; 
32、节俭; 
33、时常运用”头脑风暴“,利用脑力激荡提升自己创新能力; 
34、恪守诚信; 
35、学会原谅。

posted @ 2011-10-09 10:58 日出星辰 阅读(171) | 评论 (0)编辑 收藏

数字转换人民币大写

通过JS完成,能满足多种浏览器,不足之处是展示效果不是很理想,而且最多只能输入13位数字,希望大家提出改正方法

<html>
<head>
<title>数字转换人民币大写</title>
<script type="text/javascript">
function convert() {
var big = new Array("", "", "", "", "", "", "", "", "", "");
var unit = new Array("", "", "", "", "", "", "", "", "亿", "",
"", "", "");
var num = document.getElementById("num").value;
if (num =="") {
alert(
"输入为空,请输入数字");
return false;
}

if (num.match(/[^,.\d]/) != null) {
alert(
"输入内容不合法,请输入数字");
return false;
}
var temp = "";
if (num != null&&num.length<=13) {
for (var i = 0; i < num.length; i++) {
if(num.charAt(i)==0){
alert(
"输入内容不合法,不能以0开始");
return false;
}
else{
temp
= temp + big[num.charAt(i)] + unit[num.length - i - 1];
}

}
}
else{
alert(
"最多只能输入13位数字");
return false;
}
document.getElementById(
"rmb").innerText = temp;

}


</script>
</head>

<body>
<input type="text" name="num" id="num"/>
<input type="button" name="convert" value="转换" onclick="return convert()"/>
<input type="text" id="rmb"/>
</body>
</html>


 

 

posted @ 2011-10-08 10:36 日出星辰 阅读(182) | 评论 (0)编辑 收藏

敲回车光标跳到下一个输入框(只能在IE中使用)

<html>
<head>
<title> 敲回车光标跳到下一个输入框(只能在IE下使用) </title>
</head>
<script>
function turnNext(object){
if(object.keyCode==13){
object.keyCode
=9;
}
}
</script>
<body>
<table>
<tr>username<input type="text" name="name1" onkeydown="turnNext(event)"/></tr>
<tr>password<input type="text" name="name2" /></tr>
<tr>age<input type="text" name="name2" /></tr>
</table>
</body>
</html>

posted @ 2011-10-08 10:22 日出星辰 阅读(270) | 评论 (0)编辑 收藏

各种文件注释写法

JSP注释

在JSP中注释最好用<%----注释内容----%>

JSP注释分两种

显示注释:在客户端(源代码)可以看到

HTML中的注释<!---注释内容--->  

隐式注释:在客户端(源代码)看不到

使用JAVA中的“//”、“/*…………*/”,以及JSP中自己的注释<%----注释内容----%>

<%---JSP中的注释,看不见---%>

<%

 //注释,看不见 单行注释

 /*

 XXXXX

 注释,看不见  多行注释

 YYYYY

*/

%>

<!----显示注释--->

<!--This page was loaded on <%= (new java.util.Date()).toLocaleString() %> -->

结果:<!--This page was loaded on 2010-12-01 13:24:32 -->

如果用显示注释,浏览器也会执行里面的内容,速度会低点

HTML注释

只有一种 <!----注释内容-->

<!----这里是HTML注释--->

XML注释

只有一种<!----注释内容-->

CSS注释

只有一种 /*  注释内容 */

JavaScript注释

单行注释   //注释内容

多行注释  

/*

XXXX

注释内容

YYYY

*/

posted @ 2011-09-30 15:52 日出星辰 阅读(218) | 评论 (0)编辑 收藏

Struts1入门实例(简单登录)

现在开始加入公司的核心项目,但由于项目开发比较早,所以使用的技术不是很新潮,前台用的还是struts1。

虽然不是什么新技术,但仍可以从中学到好多东西的。花了一个晚上的时间终于把struts1的流程跑通了。

省略了创建过程及加入jar包的过程,直接进入正题。

首页要在web.xml中添加相应的struts配置:

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

然后在config所对应的目录下添加struts配置文件struts-config.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"
>

<struts-config>

<!-- ActionForm -->
<form-beans>
<!-- name:名称 type:类路径 -->
<form-bean name="loginForm" type="com.login.LoginForm">
</form-bean>
</form-beans>
<!-- 设置全局URL,必须写在Action前面,这样任何Action都可以使用 -->
<global-forwards>
<forward name="result" path="/result.jsp" />
</global-forwards>

<!-- 注册Action -->
<action-mappings>
<!-- name:名称 type:类路径 path:客户端(JSP)提交到服务器端时指定的路径(Form表单中的action=”/login.do" -->
<action path="/login" type="com.login.LoginAction"
name
="loginForm" scope="request">
<!-- 局部URL,只有这个action可以使用 -->
<forward name="success" path="/success.jsp"></forward>
<forward name="error" path="/error.jsp"></forward>
</action>
</action-mappings>


</struts-config>

注:Action和Form的关系是一个Action只能对应一个Form(通过Action的name属性)
而一个Form可以被多个Action调用
LoginAction.java
package com.login;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class LoginAction extends Action {

@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LoginForm lf
= (LoginForm) form;
String username
= lf.getUsername();
String password
= lf.getPassword();
String errorInfo
= "";
String result
= UserManager.getInstance().login(username, password);
if (result.equals("success")) {
request.setAttribute(
"username", username);
return mapping.findForward("success");
}
else if (result.equals("username")) {
errorInfo
= "密码错误";
}
else {
errorInfo
= "用户名错误";
}
request.setAttribute(
"errorInfo", errorInfo);
return mapping.findForward("error");
}

}
LoginForm.java
package com.login;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

public class LoginForm extends ActionForm {

private String username;
private String password;

public void reset(ActionMapping mapping, HttpServletRequest request) {
System.out.println(
"--------reset()-------------");
super.reset(mapping, request);
}

public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
System.out.println(
"--------validate()-------------");
return super.validate(mapping, request);
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

}
对我个人来说最重要的是前台jsp页面没有掌握,经常在页面上花费很多时间
在编写JSP页面时要用struts标签,而我经常会忘记
引入jsp标签
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<title>首页</title>
	</head>

	<body>
		<html:form action="/login.do">
			用户名:<html:text property="username"></html:text><br/>
			密码: <html:password property="password"></html:password><br/>
			<html:submit>submit</html:submit>
		</html:form>
	</body>
</html>

 

展示结果(将Action的返回值展示到JSP页面上)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<title>Error</title>
	</head>
	<body>
		<bean:write name="errorInfo" scope="request" />
	</body>
</html>

 
 

			
			

posted @ 2011-09-19 23:00 日出星辰 阅读(132) | 评论 (0)编辑 收藏

Ant学习实例

1.安装Ant

先从http://ant.apache.org/下载Ant,解压到任一目录下面,比如E:\Lab

然后设置环境变量

ANT_HOME=E:\Lab\apache-ant-1.8.2

path=E:\Lab\apache-ant-1.8.2\bin

最后验证是否安装成功

在dos中输入ant,如果显示

Buildfile: build.xml does not exist!
Build failed

则安装成功

2.基础元素

project元素

project元素是Ant文件的根元素

project的属性

Attribute

Description

Required

name

项目名称

No

default

当没有指定target时使用的缺省target

Yes

basedir

用于指定基路径的位置。该属性没有指定时,使用 Ant 的构件文件的附目录作为基准目录。

No

target元素

target为Ant的基本执行单元,它可以包含一个或多个具体的任务。多个target 可以存在相互依赖关系

Ant会依照depends属性中target出现的顺序(从左到右)依次执行每个target。然而,要记住的是只要某个target依赖于一个target,后者就会被先执行。

<target name="A"/>

<target name="B" depends="A"/>

<target name="C" depends="B"/>

<target name="D" depends="C,B,A"/>

假定我们要执行target D。从它的依赖属性来看,你可能认为先执行C,然后B,最后A被执行。错了,C依赖于B,B依赖于A,所以先执行A,然后B,

然后C,最后D被执行。

一个target只能被执行一次,即时有多个target依赖于它。

若想更好的控制build过程,可以使用if或unless。

if 属性

    用于验证指定的属性是否存在,若不存在,所在 target 将不会被执行。

unless 属性

    该属性的功能与 if 属性的功能正好相反,它也用于验证指定的属性是否存在,若不存在,所在 target 将会被执行。

property元素

property元素可看作参量或者参数的定义(即经常使用的变量),project 的属性可以通过 property 元素来设定,也可在 Ant 之外设定。

name是变量的名称 value是变量的值,要用某个变量时使用${name}方式调用。

3.完整示例

创建一个java项目

HelloWorld.java

package com.test;

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello world");
	}
}

编写build.xml文件

注:build.xml放在和src同级目录,而不是在src下级目录

目录结构是

MyProject <dir>
|--lib <dir> --库目录
|--classes <dir> --目的文件目录
|--src <dir> --源文件目录
|--doc <dir> --api文档目录
|--build.xml

<?xml version="1.0" encoding="UTF-8" ?>
<project name="helloWorld" default="run" basedir=".">
	<property name="src" value="src"/>
	<property name="dest" value="build/classes"/>
	<property name="lib" value="lib"></property>
	<property name="hello_jar" value="hello1.jar"></property>
	<!--初始化 之前执行删除操作-->
	<target name="init" depends="clean">
		<mkdir dir="${dest}"/>
	</target>
	<!--编译生成class文件 -->
	<target name="compile" depends="init">
		<javac srcdir="${src}" destdir="${dest}"></javac>
	</target>
	<!--将编译后的class文件打包-->
	<target name="build" depends="compile">
		<mkdir dir="${lib}"/>
		<jar jarfile="${lib}/${hello_jar}" basedir="${dest}"></jar>
	</target>
	<target name="run" depends="build">
		<java classname="com.test.HelloWorld" classpath="${lib}/${hello_jar}"></java>
	</target>
	<!--删除-->
	<target name="clean">
		<delete dir="${dest}"></delete>
		<delete dir="${lib}"></delete><!-- 是dir 删除目录 ,不是file 删除文件-->
	</target>
</project>
整个过程:初始化----编译----打包---放到相应的位置

参考:

http://www.cnblogs.com/philander/articles/1782254.html

http://www.cnblogs.com/elric/archive/2011/03/19/1988840.html

posted @ 2011-09-14 22:03 日出星辰 阅读(186) | 评论 (0)编辑 收藏

请不要忘记,还有“思考”这个东西【转】

【转自】http://www.cnblogs.com/tanky_woo/archive/2011/09/07/2169559.html

最近准备参加实习生招聘,于是开始关注起了各大公司的面试题,在看网易面试题的时候看到了这么一题:

为什么现在的计算机采用二进制?而不是八进制或十六进制?你认为以后的计算机会采用几进制?

我当时就在问自己,为什么?但是无果,我隐约记得很多书上都讲过,但是为了追求速度,追求更重要的知识,我把这部分内容给自动滤过了。

于是我又在想,是什么原因导致这样的呢?

我开始回忆我的学习过程,我发现,在大一大二开始接触编程时,我还是很喜欢思考的,但是为何后来就麻木了呢?

于是我又开始分析我的学习方法,没错,就是学习方法出问题了—我过于的追求速度,追求广泛,很多知识,我都是一扫而过,很多代码,我都是看一看就自以为懂了,曾经刚开始学时,我还经常把代码往电脑上敲,把代码抄在纸上,然而现在却是直接扫一下。

我想到了一个词—物极必反。虽然我看的很多,看的很快,但是收效却不大。

我突然就被惊醒了,是的,扪心自问一下,现在记在我脑海里的,还有多少知识呢?你了解的知识多吗?你看书仔细吗?

我相信很多人都和我一样,为了应付考试,应付以后的面试,工作,都在疯狂的看书,疯狂的吸纳知识,但是,你真的掌握了这些知识吗?

写到这里的时候,我又想起来我昨天在伯乐在线看到的一篇文章:学一门语言,要了解他的历史,哲学观,这也是一种思考:

比如文章中举例的:拿python来说,他的设计哲学是“用一种方法,最好是只有一种方法来做一件事”,而perl的设计哲学是“总有多种方法来做同一件事”。

其实,这是多么有趣的一件事,然后,就这样被大部分人给忽略了。想到这,我都替自己感觉到可惜。

幸好今天发现了这个问题,就像《让子弹飞》里面说的一样“步子要一步步的走,迈得大了,会扯着蛋”,确实,知识也要一步步的积累,没有什么快速掌握的方法,最好的办法就是一步一步的积累,要多思考,没有思考,就没有进步;没有思考,就没有升华。

我们应该时刻要记住,学,应该是一种享受的过程,重点不在于结果,而是过程,一种发散思维的过程。

希望自己能时刻记住这一点,能应付好接下来的实习生求职。

注:上面那个问题的答案,大家可以相互交流下,我在网上找到这篇讲的不错:

http://blog.csdn.net/hkx1n/article/details/4280036

posted @ 2011-09-08 09:10 日出星辰 阅读(135) | 评论 (0)编辑 收藏

IT草根职场必看【转】

前言:真实世界中的事情往往不是我们想象那么简单的,软件项目的复杂的业务也不是市面上的什么”精通,企业级”之类书籍能够讲述明白的。不要以为管理系统就是数据增删改查,不要以为数据相差零点零几就没有什么。

你要清楚:作为一个开发人员,你最值得骄傲的是什么,职业操守是什么。

     这里有一点需要的明白的是:公司为什么请你?说的直接一点,公司不是慈善机构,公司就是花钱请你来为她做事,创造价值的,一个不能创造价值的员工,公司会留你吗?

    终于等到了上班的那天,我对任何人都珍惜今天的这个机会,因为没有人知道,在此之前,我经历了怎样的艰辛。

    Leader给了我系统的整个数据字典(所有数据库表的图),说了一句:“理解所有表的关系,下午我给你讲讲系统的业务背景”。

     看到这里,有一点要告诉大家的是:不要再天真的以为公司会花几个星期,几个月的事情,让你慢慢的熟悉业务,熟悉相关的知识,一切要靠自己去快速的领悟与消化,这是一个“物竞天择,能者居之”的社会,不是没有谁就不行。

    说道这里,打个岔!同时这里给刚刚毕业或者踏入整个行业的朋友们提个醒:不要再以自己大学多么有名而骄傲,也不要再因为自己以前的成绩多么的好而得以。一个人的学习能力就决定了他以后发展的深度和广度。胸怀决定发展的高度!

     不要再以为有人会像老师那样一行行的解释代码是什么意思,不要以为你是新人,犯错就是“理所当然”。No excuse!

     在公司,我是最小的,周围都是有几年工作经历的同事,还有四十多岁的。如果公司要裁人(在中国it),那么新人和年纪很大的就是目标群体(在你没有核心竞争力和很好的人缘之前),新人是最大的目标!压力!

     毕竟自己从大二就开始在外面兼职和实习,这点觉悟还是有的。所以,接到这第一个任务之后,自己开始行动起来。

     面对上百张数据表,无疑是个负责的蜘蛛网,怎么办?那就得看你如何处理了。如果说,你要找人帮忙,也得“察言观色”。下面,我们就细细说来。

     首先说如何理解上百张表,无疑,从系统的功能入手时最快速的。系统的功能一般是分模块实现的,那么表势必和相关的功能挂钩,那么把表按照功能划分来看,就很方便了。

     所以这里就告诫朋友们一点:要学会逆向思维。一直做项目的时候,总是先设计功能,让后设计表,是吧!现在反推,从表到功能,再回到表,就能够把问题变得简单一点!不要以为这很简单,我这里只是一个简单的例子而已,如果问题更加复杂,怎么办?!

     因为我是新人,计算机的权限有限,很多的资源都不能访问,也没有开通查看代码的权限。但是,我现在需要可以运行的系统来帮助我,怎么办?

那么就涉及到第二个问题,如何找人帮忙?

     不要傻不拉几的一上去就随便找个人,然后开口说:“帮我一下“!要知道,人家凭什么帮你?人家有事情要忙吗?这个世界没有谁帮助谁是理所当然的!感激帮助过你的朋友和亲人吧!

      所以,要学会“察言观色“,这里不是贬义词!做人要灵光点

      首先,最好请示leader,问他是否有时间?态度要好!如果没有,那么就要问他,除了他还有谁可以问。

      当问另外一个人的时候,首先要观察这个人是不是忙的那种不可开交的样子,如果是,那么,现在最好不要问,而是自己再次评估一下,如果要找人帮忙,估计要花人家多长的时间?如何估算,这就是个人的本事了,呵呵!我这里暂且不说,免得又朋友说“你不说,我也知道“ !呵呵!

      然后,等自己这边时间也估计好之后,然后态度很好的告诉你需要寻求帮助的人:“可以打扰你几分钟吗“,然后,你就告诉他,你需要系统的一个可以运行的版本! 如果人家没有时间,不要退缩,你就要追问,估计什么时候可以有时间,是否有文档,先让自己熟悉下。然后你就到那个点在再去问,不要忘记,随时注意态度!

     不管如何,不要靠指望别人,要靠自己的一些经验或相关文档,尽力的理解。一句话,用心的,带着脑子做事情!

posted @ 2011-09-07 21:05 日出星辰 阅读(131) | 评论 (0)编辑 收藏

各种创建单例模式的优缺点

单例模式应用于一个类只有一个实例的情况,并且为其实例提供一个全局的访问点。

特点

1.一个类只有一个实例

2.自己创建这个实例

3.整个系统只能用这个实例

应用场景

外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。

内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件。

实现方式

1.饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)

/**
 * 饿汉式(推荐)
 *
 */
public class Singleton1 {

	private Singleton1() {
	}

	public static Singleton1 instance = new Singleton1();

	public Singleton1 getInstance() {
		return instance;
	}

}

优点 1.线程安全
2.在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点 资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化

 

2.懒汉式:单例实例在第一次被使用时构建,延迟初始化。

class Singleton2 {
	private Singleton2() {
	}

	public static Singleton2 instance = null;

	public static Singleton2 getInstance() {
		if (instance == null) {
              //多个线程判断instance都为null时,在执行new操作时多线程会出现重复情况
			instance = new Singleton2();
		}
		return instance;
	}
}

懒汉式在单个线程中没有问题,但在多线程就可能会出现两个或多个Singleton2实例情况,

虽然后面实例化的Singleton2会覆盖前面实例化的Singleton2,但最好避免这样的情况。

改进方式就是加锁synchornized

class Singleton3 {
	private Singleton3() {
	}

	public static Singleton3 instance = null;

	public static synchronized Singleton3 getInstance() {
		if (instance == null) {
			instance = new Singleton3();
		}
		return instance;
	}
}
优点 资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法
缺点 第一次加载时不够快,多线程使用不必要的同步开销大


3.双重检测

class Singleton4 {
	private Singleton4() {
	}

	public static Singleton4 instance = null;

	public static Singleton4 getInstance() {
		if (instance == null) {
			synchronized (Singleton4.class) {
				if (instance == null) {
					instance = new Singleton4();
				}
			}
		}
		return instance;
	}
}

优点 资源利用率高,不执行getInstance()就不被实例,可以执行该类其他静态方法
缺点 第一次加载时反应不快,由于java内存模型一些原因偶尔失败

 

4.静态内部类

class Singleton5 {
	private Singleton5() {
	}

	private static class SingletonHelp {
		static Singleton5 instance = new Singleton5();
	}

	public static Singleton5 getInstance() {
		return SingletonHelp.instance;
	}
}

优点 资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法
缺点 第一次加载时反应不够快

 

总结:一般采用饿汉式(1),若对资源十分在意可以采用静态内部类(4),不建议采用懒汉式及双重检测(2、3)

另外

对于第二种可以采用volatile方式

volatile用更低的代价代替同步

解释:同步的代价主要有覆盖范围决定,如果可以降低同步的覆盖范围,可大幅提升性能。

而volatile覆盖范围是变量级别的,因此同步代价很低。

volatile原理:告诉处理器,不要将其放入工作内存,而是直接在主存操作。因此,当多处理器或多线程在访问该变量时

都将直接操作主存,这在本质上做到了变量共享。

volation优势:

1.更大的程度吞吐量

2.更少的代码实现多线程

3.程序伸缩性好

4.比较好理解,无需太高的学习成本

volatile不足:

1.容易出问题

2.比较难设计

参考文献

http://yiminghe.iteye.com/blog/404334

http://developer.51cto.com/art/201103/249322.htm

posted @ 2011-09-05 21:54 日出星辰 阅读(3369) | 评论 (0)编辑 收藏

线程学习笔记【5】--ThreadLocal应用

基本的ThreadLocal使用

public class ThreadLocalTest {

static ThreadLocal tl=new ThreadLocal();
public static void main(String[] args) {

for(int i=0;i<2;i++){
new Thread(new Runnable(){
int data =new Random().nextInt();
public void run() {
System.out.println(Thread.currentThread().getName()
+"存入的数据是 "+data);
tl.set(data);
//存到了当前线程
new A().getThreadData();
}
}).start();
}
}
static class A{ //静态类相当于一个外部类
public void getThreadData(){
System.out.println(
"data is "+tl.get());
}
}
}

结果可能是

Thread-0存入的数据是 1997234255
Thread-1存入的数据是 267171693
data is 1997234255
data is 267171693

通过包装对象非常烂的使用方式

class MyThreadScopeData{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

 

public class ThreadLocalTest {
static ThreadLocal<MyThreadScopeData> myThreadScopeData=
new ThreadLocal<MyThreadScopeData>();
public static void main(String[] args) {

for(int i=0;i<2;i++){
new Thread(new Runnable(){
int data =new Random().nextInt();
public void run() {
MyThreadScopeData mydata
=new MyThreadScopeData();
mydata.setName(
"name is name"+data);
mydata.setAge(data);
//把对象存入ThreadLocal 这样的做法非常烂!!!!!
myThreadScopeData.set(mydata);
                  new B().showThreadScopeData();

}
}).start();
}
}


static class B{
public void showThreadScopeData(){
System.out.println(myThreadScopeData.get().getName());
System.out.println(
"age is "+myThreadScopeData.get().getAge());
}
}

}

}

标准使用方式

/**
* 单列线程
* 在线程中范围内任意地方调,得到都是同一个实例对象
* 把ThreadLocal封装到单列的内部
*/
class ThreadSingle{
private ThreadSingle(){}
public static ThreadLocal<ThreadSingle> map=new ThreadLocal<ThreadSingle>();
//不需要加synchronized,即便有第2个线程进入,但拿到的map.get()是独有的。
public static ThreadSingle getThreadInstance(){ //方法得到是与本线程相关的实例
ThreadSingle obj=map.get();
/**
* 如果A进入时obj=null,刚创建完还没赋值,此时B线程进入,但B和A没有关系。
*/
if(obj==null){
obj
=new ThreadSingle();
map.set(obj);
}
return obj;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

}

 

 

public class ThreadLocalTest {

	public static void main(String[] args) {

		for(int i=0;i<2;i++){
			new Thread(new Runnable(){
				int data =new Random().nextInt();
				public void run() {						
					ThreadSingle.getThreadInstance().setName("name"+data);
					ThreadSingle.getThreadInstance().setAge(data);
					new C().showData();
				}
			}).start();
		}
	}

 

 

 

 

 

 

 

posted @ 2011-09-05 15:31 日出星辰 阅读(130) | 评论 (0)编辑 收藏