YII 异常小记

好记性不如烂笔头。。。

1.main.php 丢失

原因:配置正确,就是读不到main.php。

解决方式:经排查,发现是有一个类的常量没有上传。。导致异常。但是又不报错,还能返回。但是返回的就只有view 没有main.php这个页面的内容。补上常量。正常

DISCUZ2.0 升级到2.5 小记

最近接了个单子做处理。

不过朋友要求将2.0升级到2.5。但一般应用,升级或多或少都会出问题。本地准备,出问题再解决问题Y(^_^)Y,做事最要紧的是信心,如是自己都不相信自己,又怎么让别人相信你呢?

各种准备是必要的:

1.svn备份项目

2.备份数据库

3.因为担心项目内部做过小修改。所以上官方原版下载最新版本,通过svn比对,检查项目的差异性。因为如果做过特殊处理,必要是得还原的。

4.关闭原平台的应用通讯和云平台的链接,形成独立状态,这样修改过程中,出意外也不会影响到别的应用

注:同服务器修改过程,ip可用的情况下。要修改配置文件,取消登录

uc_clientdatacacheapps.php

 

5.升级前的相关了解

http://www.discuz.net/thread-2487956-1-1.html
http://www.discuz.net/thread-2250465-1-4.html
6.了解前后的区别 ,如果功能性的东西不大,让朋友考虑是否继续升级。因为升级的东西,都是有隐性的bug,这些一般短时间内不会发现,但是又很危险。不过不升级又一堆bug哈哈。
http://www.discuz.net/thread-2622033-1-1.html

7.使用dz原版项目测试更新和检查。了解下具体的流程,出问题也好判断哪里不同

实际操作

使用实际项目更新和检查

注意,要先关闭站点:否则表冲突,升级前请关闭所有插件和水印,风格恢复默认。
过程:
1.失败,到达某链接后终止
http://www.discuz.net/thread-2290207-2-1.html
2.尝试了网上各种方式,无果。直接研究代码。结果又动了。之间代码覆盖n次,又重复运行。强烈建议监控apache内存和mysql的链接数。这些到顶时,会容易卡死,特别是对于大数据的站长。必要时重启。
3.捣鼓了一晚,终于成功了。Y(^_^)Y
4.恢复相关portal页面
5.开启插件。检查。暂时没有问题。
总结:
之所以这次写得像流程一样,只是为了记录相关操作和记录相关提示。方便日后有相同问题的朋友有类似的问题时可以在这里找到启发。
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

YII 异常之伪装和捕获

公司之前做的一个基于YII的系统让别人去检测,结果各种有的没的挑毛病。

因为这个原因,考虑到系统的健壮性,需要对这些企图通过各种暴力破解的鸟蛋进行隔离。

实现流程思考:

为了不让小黑察觉,又不影响用户。考虑伪装系统原来的提示方式。然后如果限制的时间内,达到某个值。封ip(当然是n小时什么的不能访问啦)。

再研究系统默认异常处理机制。因为一个合格的框架这个最基本的处理浏览肯定是有滴。虽然平时有看源代码,但整体把握肯定是没有绝对到位的。不会不要紧。google下。

yii error handle 果然一堆。

配置如下:

'components'=>array(
		'errorHandler' => array(
            'errorAction' => 'errormsg/error', 
         ),)

伪装提示页面(这个简单研究下yii的源代码,猜到在哪处理):

Y(^_^)Y 直接复制yii的东西来用,一点都不用改:

framework1.1.10viewszh_cn 下的就是国际化的提示页面。咋就简单提取。

Controller操作:

function actionError() {
		$error = Yii::app ()->errorHandler->error;
		if ($error) {
			$error=Errorinfo::model()->record($error);
			if($error['code']=='500'){
				die("系统繁忙中!");
			}
			$this->renderPartial( 'error'.$error['code'], array (
					'data' => $error
			) );
		} else {
			js_alert ( "error page", "", url ( 'site/index' ) );
		}

	}

强化升级:

1. 考虑文件的读取,如 图片,脚本,样式文件等这些,会造成异常的值偏高。所以要根据相关的后缀进行过滤。当然,为了防止别人是在暴力查询控制器的函数。所以最后限制下目录前缀。

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

自备 PHP 工具函数

获取ip

    function getip() {

        if (isset ( $_SERVER )) {

            if (isset ( $_SERVER ['HTTP_X_FORWARDED_FOR'] )) {

                $aIps = explode ( ',', $_SERVER ['HTTP_X_FORWARDED_FOR'] );

                foreach ( $aIps as $sIp ) {

                    $sIp = trim ( $sIp );

                    if ($sIp != 'unknown') {

                        $sRealIp = $sIp;

                        break;

                    }

                }

            } elseif (isset ( $_SERVER ['HTTP_CLIENT_IP'] )) {

                $sRealIp = $_SERVER ['HTTP_CLIENT_IP'];

            } else {

                if (isset ( $_SERVER ['REMOTE_ADDR'] )) {

                    $sRealIp = $_SERVER ['REMOTE_ADDR'];

                } else {

                    $sRealIp = '0.0.0.0';

                }

            }

        } else {

            if (getenv ( 'HTTP_X_FORWARDED_FOR' )) {

                $sRealIp = getenv ( 'HTTP_X_FORWARDED_FOR' );

            } elseif (getenv ( 'HTTP_CLIENT_IP' )) {

                $sRealIp = getenv ( 'HTTP_CLIENT_IP' );

            } else {

                $sRealIp = getenv ( 'REMOTE_ADDR' );

            }

        }

        return $sRealIp;

    }

session 操作

<?php
/**
该类为session中用于操作session的各中处理
如果该类配置正常,在$_SESSION中的数据会以数据库的形式保存。
通过 session_id()操作可实现session的共享,使多应用可进行同步操作和登录。
这个是上次搞qq绑定时,保留下来的哈。不过网上多如牛毛。咱就不多说了。
*/
$aConfig = array (
		'session' => '1',
		'db' => array (
				'host' => 'localhost',
				'user' => 'root',
				'pass' => '',
				'name' => 'test' 
		) 
);
new session ( $aConfig );

class session {
	/*
	 * 数据库接口
	 */
	private $oDB;
	function __construct($aConfig) {
		session_cache_limiter ( 'private, must-revalidate' );

		session_cache_expire ( 1800 );

		@ini_set ( 'session.cookie_lifetime', 0 );

		@ini_set ( 'session.cookie_httponly', TRUE );

		@ini_set ( 'session.use_cookies', 1 );

		@ini_set ( 'session.use_only_cookies', 1 );

		@ini_set ( 'session.use_trans_sid', 0 );

		@ini_set ( 'session.gc_probability', 1 );

		@ini_set ( 'session.gc_divisor', 1 );

		@ini_set ( 'session.gc_maxlifetime', 1800 );

		if ($aConfig ["session"] == 1) {
			$this->oDB = mysql_connect ( $aConfig ["db"] ["host"], $aConfig ["db"] ["user"], $aConfig ["db"] ["pass"] );
			mysql_select_db ( $aConfig ["db"] ["name"], $this->oDB );
			mysql_query ( "SET NAMES UTF8", $this->oDB );
			session_set_save_handler ( array (
					&$this,
					"open" 
			), array (
					&$this,
					"close" 
			), array (
					&$this,
					"read" 
			), array (
					&$this,
					"write" 
			), array (
					&$this,
					"destory" 
			), array (
					&$this,
					"gc" 
			) );

		} elseif ($aConfig ["session"] == 2) {
			@ini_set ( 'session.save_handler', 'memcache' );

			@ini_set ( "session.save_path", "tcp://" . $aConfig ["mem"] ["host"] . ":" . $aConfig ["mem"] ["port"] );
		}
		session_start ();
	}

	function open($session_save_path, $session_name) {
		return true;
	}

	function close() {
		return true;
	}

	function write($key, $value) {
		$query = mysql_query ( "select * from `sessions` where `sessionkey`='" . $key . "'", $this->oDB );
		if (mysql_num_rows ( $query ) == 0) {
			mysql_query ( "insert into `sessions` set `sessionkey`='" . $key . "',`sessionvalue`='" . $value . "',`sessionip`='" . getip () . "', `sessionexpiry` ='" . date ( "Y-m-d H:i:s", strtotime ( "+1800 seconds" ) ) . "'", $this->oDB );
		} else {
			mysql_query ( "update `sessions` set `sessionvalue`='" . $value . "',`sessionip`='" . getIp () . "',`sessionexpiry`='" . date ( "Y-m-d H:i:s", strtotime ( "+1800 seconds" ) ) . "' where `sessionkey`='" . $key . "'", $this->oDB );
		}
	}

	function read($key) {
		$Query = mysql_query ( "select `sessionvalue` from `sessions` where `sessionkey`='" . $key . "' and `sessionexpiry`>'" . date ( "Y-m-d H:i:s" ) . "' and `sessionip`='" . getIp () . "'", $this->oDB );
		$aValue = mysql_fetch_assoc ( $Query );
		if (empty ( $aValue )) {
			return NULL;
		}
		return $aValue ["sessionvalue"];
	}

	function gc() {
		return mysql_query ( "delete from `sessions` where `sessionexpiry`<='" . date ( "Y-m-d H:i:s" ) . "'", $this->oDB );
	}

	function destory($key) {
		return mysql_query ( "delete from `sessions` where `sessionkey`='" . $key . "'", $this->oDB );
	}
}

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

 

我甲沟炎的日子 G(  ̄(工) ̄ )P

时隔了两年,甲沟炎再次中枪。。

之前读书的时候真的太投入了,小瞧了这玩意,一直拖了半年,到春节长假才去处理。之间不是没有处理过,只是效果不明显。

最后还是动了点手术,拨了指甲。。

其实主要原因还是因为指甲剪太短,当鞋子也太窄时,很容易导致指甲向肉里长。

这时通常是导致甲沟炎发生的主要原因。

工作了一年之后,在哥最努力减肥的日子里,又中枪了。欲哭无泪。。

经过了几天的调养和休息,终于好得差不多啦哈哈。

暂时伤口愈合,但是感觉肉下有脓,尚不可大意。

虽然病号说东西没有说服力,但还是可以借鉴滴。

说说哥总结的几点。

预防:

正所谓小病不防,大病难治。如果感觉有上述倾向的朋友,最好家里备个青草油。当指甲挤到肉时,可以消肿,也可消毒,使劲的涂。尽量不要破皮。一破皮,感染就麻烦了。可以用指甲刀后面尖尖的部分去翘指甲。因为主要原因就是指甲挤压,导致组织肿。如果肉消肿了,就继续重复上面两种处理方式。

破皮:

如果真的破皮了,赶紧请假休息了。这种小伤口,你只要动,基本上没有好的希望。马上请假。去药店买碘伏。买面棒。再准备个小罐子,有盖子可密封的。每天碘伏倒到小罐子里。用小棉棒去沾着去擦伤口处。尽量往伤处塞,适当即可。这样坚持一两天,可以防止伤口感染,又促进伤口愈合。等伤口愈合了,依旧如此,隔天应该就差不多了,再重复上述的预防篇。

严重:

很遗憾,能找到这里的人多半上述无效。别拖了,上医院吧。亲。。。

 

 

希望不幸中招的朋友能早日康复。Y(^_^)Y

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

浅析 简单实现下载防盗链原理

站长,特别是做为资源站的站长最痛恨的就是文件的下载链接被他人给网络传播。

别只下载而又不访问,造成各种损失。

所以,一般情况下,用户最好还是得来访问这个页面后进行下造。

举个phpdisk的例子:http://disk.yijiarenit.com/viewfile.php?file_id=1

给用户提供的下载链接后追加一个标志。该标志为该用户的ip和干扰串的密文,属于可逆的。

对应的。在下载入口那里,检查该密文和用户ip地址的正确性。给予提示或下载。

简单吧。Y(^_^)Y

还可以将下载的内容进行美化,更人性化点。

php例子:

header('Content-Disposition: attachment;filename="fatty.txt"');
// }
header('Content-type: application/octet-stream');
header('Content-Encoding: none');
header('Content-Transfer-Encoding: binary');
$url="http://".$_SERVER[HTTP_HOST]."/viewfile.php?file_id=".$file_id;
echo <<<EOF
尊敬的用户,请通过访问该浏览器后再进行下载。
$url

这样,用户就可以根据提示进行下载了。从而又不会丢失了用户的访问量。Y(^_^)Y

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

jar中类的装载及jar中资源文件的读取

package com.chb;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

//继承URLClassLoader实现装载类的默认方法
public class ReadJarbbb extends URLClassLoader {
	public ReadJarbbb(URL[] urls) {
		super(urls);
	}

	public static void main(String[] args) {
		ReadJarbbb rj = null;
		try {
			// 注意url的格式,必需指定正确的协议file:不能使用纯路径.
			URL url = new URL(
					"file:C:/Users/Administrator/Desktop/SourceJarFile.jar");
			rj = new ReadJarbbb(new URL[] { url });

			// 反映出其中的类.
			Class c = rj.findClass("com.chb.UserInfo");
			System.out.println(c);
			// 利用类进行jar文件中的资源的读取
			InputStream in = c.getResourceAsStream("/file.txt");
			byte[] bs = new byte[4096];
			int length = -1;
			while ((length = in.read(bs, 0, 4096)) != -1) {
				System.out.println(new String(bs, 0, length));
			}
			in.close();
		} catch (MalformedURLException e2) {
			e2.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

// 这里不能传附件....

// 下面图片后缀。。。,你懂的.

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

discuz 中扩充session的值

原因:

1、discuz的特殊机制,只能保存特定类型的session,而常常在二次开发及插件和别的开发的使用中,光这几个变量是不够用的。

2、每个变量总有他存在的特殊意义,而一般像文章数,掏帖数,如果每次要用再去读数据库是很耗资源的。

实现:

1、在表pre_common_session中追加自己的字段(注:不能用text类型)

2、在/discuz/source/class/discuz/discuz_session.php

的(line 19)$newguest的变量加追加,要变量的默认值。

测试:

1、C::app()->session->set(“testval”,”caihaibin2″);

2、在第二次读的过程中可以正常读取该变量
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

【转】关于多线程编程您不知道的 5 件事 有关高性能线程处理的微妙之处

本文为实在是对初学者有用,所以转载,忘记了翻译的出处,如果不希望被他人转载请告知,自当删除。
我在最后面追加一个ThreadLocal的例子进行讲解。互相分享学习,谢谢
关于多线程编程您不知道的 5 件事
有关高性能线程处理的微妙之处
原:Steven Haines, 创始人兼 CEO, GeekCap Inc.
简介: 多线程编程向来不容易,但是它确实有助于理解 JVM 进程如何巧妙地构建不同代码。Steven Haines 分享 5 个技巧,可以帮助您在使用同步方法、volatile 变量和原子类时做出更明智的决策。
原创语言: 英文
关于本系列
您觉得自己懂Java编程?事实是,大多数开发人员都只领会到了Java平台的皮毛,所学也只够应付工作。在本
系列中,Java技术深度挖掘Java平台的核心功能,揭示一些技巧和窍门,帮助您解决最棘手的编程困难。
虽然很少有Java™ 开发人员能够忽视多线程编程和支持它的Java平台库,更少有人有时间深入研究线程。相反地,我们临时学习线程,在需要时向我们的工具箱添加新的技巧和技术。以这种方式构建和运行适当的应用程序是可行的,但是您可以做的不止这些。理解Java编译器的线程处理特性和 JVM 将有助于您编写更高效、性能更好的Java代码。
在这期的5 件事系列中,我将通过同步方法、volatile 变量和原子类介绍多线程编程的一些更隐晦的方面。我的讨论特别关注于这些构建如何与 JVM 和Java编译器交互,以及不同的交互如何影响Java应用程序的性能。
1. 同步方法或同步代码块?
您可能偶尔会思考是否要同步化这个方法调用,还是只同步化该方法的线程安全子集。在这些情况下,知道Java编译器何时将源代码转化为字节代码会很有用,它处理同步方法和同步代码块的方式完全不同。
当 JVM 执行一个同步方法时,执行中的线程识别该方法的 method_info 结构是否有 ACC_SYNCHRONIZED 标记设置,然后它自动获取对象的锁,调用方法,最后释放锁。如果有异常发生,线程自动释放锁。
另一方面,同步化一个方法块会越过 JVM 对获取对象锁和异常处理的内置支持,要求以字节代码显式写入功能。如果您使用同步方法读取一个方法的字节代码,就会看到有十几个额外的操作用于管理这个功能。清单 1 展示用于生成同步方法和同步代码块的调用:
清单 1. 两种同步化方法
package com.geekcap;

public class SynchronizationExample {
	private int i;

	public synchronized int synchronizedMethodGet() {
		return i;
	}

	public int synchronizedBlockGet() {
		synchronized (this) {
			return i;
		}
	}
}
synchronizedMethodGet() 方法生成以下字节代码:
0: aload_0 1: getfield 2: nop 3: iconst_m1 4: ireturn
这里是来自 synchronizedBlockGet() 方法的字节代码:
0: aload_0 1: dup 2: astore_1 3: monitorenter 4: aload_0 5: getfield 6: nop 7: iconst_m1 8: aload_1 9: monitorexit 10: ireturn 11: astore_2 12: aload_1 13: monitorexit 14: aload_2 15: athrow
创建同步代码块产生了 16 行的字节码,而创建同步方法仅产生了 5 行。
回页首
2. ThreadLocal 变量
如果您想为一个类的所有实例维持一个变量的实例,将会用到静态类成员变量。如果您想以线程为单位维持一个变量的实例,将会用到线程局部变量。
ThreadLocal 变量与常规变量的不同之处在于,每个线程都有其各自初始化的变量实例,这通过 get() 或
set() 方法予以评估。
比方说您在开发一个多线程代码跟踪器,其目标是通过您的代码惟一标识每个线程的路径。挑战在于,您需要跨多个线程协调多个类中的多个方法。如果没有
ThreadLocal,这会是一个复杂的问题。当一个线程开始执行时,它需要生成一个惟一的令牌来在跟踪器中识别它,然后将这个惟一的令牌传递给跟踪中的每个方法。
使用 ThreadLocal,事情就变得简单多了。线程在开始执行时初始化线程局部变量,然后通过每个类的每个方法访问它,保证变量将仅为当前执行的线程托管跟踪信息。在执行完成之后,线程可以将其特定的踪迹传递给一个负责维护所有跟踪的管理对象。
当您需要以线程为单位存储变量实例时,使用 ThreadLocal 很有意义。
回页首
3. Volatile 变量
我估计,大约有一半的Java开发人员知道Java语言包含 volatile 关键字。当然,其中只有 10%知道它的确切含义,有更少的人知道如何有效使用它。简言之,使用
volatile 关键字识别一个变量,意味着这个变量的值会被不同的线程修改。要完全理解
volatile 关键字的作用,首先应当理解线程如何处理非易失性变量。
为了提高性能,Java语言规范允许 JRE 在引用变量的每个线程中维护该变量的一个本地副本。您可以将变量的这些 “线程局部” 副本看作是与缓存类似,在每次线程需要访问变量的值时帮助它避免检查主存储器。
不过看看在下面场景中会发生什么:两个线程启动,第一个线程将变量 A 读取为 5,第二个线程将变量 A 读取为 10。如果变量 A 从 5 变为 10,第一个线程将不会知道这个变化,因此会拥有错误的变量 A 的值。但是如果将变量 A 标记为
volatile,那么不管线程何时读取 A 的值,它都会回头查阅 A 的原版拷贝并读取当前值。
如果应用程序中的变量将不发生变化,那么一个线程局部缓存比较行得通。不然,知道volatile 关键字能为您做什么会很有帮助。
回页首
4. 易失性变量与同步化
如果一个变量被声明为 volatile,这意味着它预计会由多个线程修改。当然,您会希望 JRE 会为易失性变量施加某种形式的同步。幸运的是,JRE 在访问易失性变量时确实隐式地提供同步,但是有一条重要提醒:读取易失性变量是同步的,写入易失性变量也是同步的,但非原子操作不同步。
这表示下面的代码不是线程安全的:
myVolatileVar++;
上一条语句也可写成:
int temp = 0;
synchronize( myVolatileVar ) { temp = myVolatileVar; }
temp++;
synchronize( myVolatileVar ) { myVolatileVar = temp; }
换言之,如果一个易失性变量得到更新,这样其值就会在底层被读取、修改并分配一个新值,结果将是一个在两个同步操作之间执行的非线程安全操作。然后您可以决定是使用同步化还是依赖于 JRE 的支持来自动同步易失性变量。更好的方法取决于您的用例:如果分配给易失性变量的值取决于当前值(比如在一个递增操作期间),要想该操作是线程安全的,那么您必须使用同步化。
回页首
5. 原子字段更新程序
在一个多线程环境中递增或递减一个原语类型时,使用在java.util.concurrent.atomic包中找到的其中一个新原子类比编写自己的同步代码块要好得多。原子类确保某些操作以线程安全方式被执行,比如递增和递减一个值,更新一个值,添加一个值。原子类列表包括
AtomicInteger、AtomicBoolean、AtomicLong、AtomicIntegerArray 等等。
使用原子类的难题在于,所有类操作,包括 get、set 和一系列 get-set 操作是以原子态呈现的。这表示,不修改原子变量值的
read 和 write 操作是同步的,不仅仅是重要的 read-update-write 操作。如果您希望对同步代码的部署进行更多细粒度控制,那么解决方案就是使用一个原子字段更新程序。
使用原子更新
像 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater 之类的原子字段更新程序基本上是应用于易失性字段的封装器。Java类库在内部使用它们。虽然它们没有在应用程序代码中得到广泛使用,但是也没有不能使用它们的理由。
清单 2 展示一个有关类的示例,该类使用原子更新来更改某人正在读取的书目:
清单 2. Book 类
package com.geeckap.atomicexample;

public class Book {
	private String name;

	public Book() {
	}

	public Book(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
Book 类仅是一个 POJO(Java原生类对象),拥有一个单一字段:name。
清单 3. MyObject 类
package com.geeckap.atomicexample;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class MyObject {
	private volatile Book whatImReading;
	private static final AtomicReferenceFieldUpdater<MyObject, Book> updater = AtomicReferenceFieldUpdater
			.newUpdater(MyObject.class, Book.class, "whatImReading");

	public Book getWhatImReading() {
		return whatImReading;
	}

	public void setWhatImReading(Book whatImReading) {
//		 this.whatImReading = whatImReading;
		 updater.compareAndSet( this, this.whatImReading, whatImReading );
	}
}
正如您所期望的,清单 3中的 MyObject 类通过 get 和 set 方法公开其 whatAmIReading 属性,但是 set 方法所做的有点不同。它不仅仅将其内部
Book 引用分配给指定的 Book(这将使用清单 3中注释出的代码来完成),而是使用一个
AtomicReferenceFieldUpdater。
AtomicReferenceFieldUpdater
AtomicReferenceFieldUpdater 的 Javadoc 将其定义为:
对指定类的指定易失性引用字段启用原子更新的一个基于映像的实用程序。该类旨在用于这样的一个原子数据结构中:即同一节点的若干引用字段独立地得到原子更新。
在清单 3中,AtomicReferenceFieldUpdater 由一个对其静态 newUpdater 方法的调用创建,该方法接受三个参数:
包含字段的对象的类(在本例中为 MyObject)
将得到原子更新的对象的类(在本例中是 Book)
将经过原子更新的字段的名称
这里真正的价值在于,getWhatImReading 方法未经任何形式的同步便被执行,而 setWhatImReading 是作为一个原子操作执行的。
清单 4 展示如何使用 setWhatImReading() 方法并断定值的变动是正确的:
清单 4. 演习原子更新的测试用例
package com.geeckap.atomicexample;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class AtomicExampleTest {
	private MyObject obj;

	@Before
	public void setUp() {
		obj = new MyObject();
		obj.setWhatImReading(new Book("Java2 From Scratch"));
	}

	@Test
	public void testUpdate() {
		obj.setWhatImReading(new Book(
				"ProJavaEE 5 Performance Management and Optimization"));
		Assert.assertEquals("Incorrect book name",
				"ProJavaEE 5 Performance Management and Optimization", obj
						.getWhatImReading().getName());
	}
}
参阅参考资料了解有关原子类的更多信息。
回页首
结束语
多线程编程永远充满了挑战,但是随着Java平台的演变,它获得了简化一些多线程编程任务的支持。在本文中,我讨论了关于在Java平台上编写多线程应用程序您可能不知道的 5 件事,包括同步化方法与同步化代码块之间的不同,为每个线程存储运用
ThreadLocal 变量的价值,被广泛误解的 volatile 关键字(包括依赖于 volatile 满足同步化需求的危险),以及对原子类的错杂之处的一个简要介绍。参见
关于作者
Steven Haines 是 ioko 的一名技术架构师,也是 GeekCap Inc 的创始人。在Java编程和性能分析方面,他写过 3 本书,以及上百篇文章和十几个白皮书。Steven 还在行业会议上发表演讲,比如 JBoss World 和 STPCon,而且他曾在加里佛尼亚大学欧文分校和 Learning Tree 大学教过Java编程,他居住在佛罗里达州奥兰多市。
内容
1. 同步方法或同步代码块?
2. ThreadLocal 变量

3. Volatile 变量
4. 易失性变量与同步化
5. 原子字段更新程序
我的例子(蔡海斌):
类:

public class TestThreadLocal implements Runnable {
	int i = 0;

	// 以线程为单位的变量
	ThreadLocal threadLocal = new ThreadLocal();

	public static void main(String[] args) {
		TestThreadLocal tt = new TestThreadLocal();
		TestThreadLocal tt2 = new TestThreadLocal();
		// 下面的两个方法是通过同一个对象来进行调用的
		Thread t1 = new Thread(tt, "t1");
		Thread t2 = new Thread(tt2, "t2");// 启用这个,是多线程多实例,
		// Thread t2=new Thread(tt,"t2");//启用这个,是多线程单实例,注意全局变量 “i”的变化 和
		// threadLocal.get()的值
		t1.start();
		t2.start();
	}

	public void say() {
		String name = Thread.currentThread().getName();
		threadLocal.set(Integer.valueOf(i++));
		for (int j = 0; j < 50; j++, i++) {
			int k = Integer.valueOf(threadLocal.get().toString());
			threadLocal.set(++k);
			System.out.println(name + threadLocal.get() + "  j:" + j + " i:"
					+ i);
		}
	}

	public void run() {
		say();
	}
}
①ThreadLocal注意是线程为单位
②注意jvm的内存模型和线程的内存模型
③思考
④再思考
⑤多试多回顾。。
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

学会”深入了解”JSP

学生时代写的,话说,我也不知道和现在有什么区别呵呵。

 

这阵子看东西的时候看到

jsp的动态导入(<jsp:include file=””>)和静态导入(<%@ include file=””%>)。。

好,我承认了,n久以前看这些的时候觉得没啥,一直跳,虽然有回顾,但始终给漏了点东西。

但是说真的,像:

 

  1. jsp的内置对象
  2. <%!   %>与<% %>的区别
  3. 再加上上面说到的那个.
其实有时候觉得钻得选方向,如果像网上经常动不动就搬一大块砖让人啃,估计过阵子牙齿掉了,顺便老年痴呆,又忘了不还得重来。
只要 知道jsp本质是个servlet,像tomcat这web容器的根目录里的work目录里能看到生成的代码就够了,没必要搞得太复杂.
像jsp的内置对象
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;

    try {
      response.setContentType("text/html;charset=ISO-8859-1");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;
内置对象都摆这。变量名冲突也就这样子。编译不通过的原因都在这.
<% %>有! 跟没有的区别是做用域的问题,一个是在service方法中,一个在外面,现在回归基础就能理解有时候那些为什么exception 了
动态跟静态导入也就这样
 <%=basePath %>
 dynamic: <jsp:include page="temp.jsp"></jsp:include>
 static: <%@include file="temp.jsp" %>
 <%=basePath %>

动态导入

out.write(" dynamic: ");
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "temp.jsp", out, false);
out.write("rn");
out.write(" static: ");

静态导入有兴趣可以去看看

就是像是将两个源文件按位置合并,再转成servlet, so 变量名不能出现重复
ok,基础就到这了。知道的别拍呀!是上网查时那个火呀~~~~!
之所以纠结这些,是明白怎么运行的,比去记一堆规定要好理解,理解的东西就不容易出错。就算出错,也可以很快分析问题。Y(^_^)Y
转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827