博文
一段比较经典的多线程学习代码(2006-08-03 11:12:00)
摘要:
一段比较经典的多线程学习代码。
1、用到了多线程的同步问题。
2、用到了多线程的顺序问题。
如果有兴趣的请仔细阅读下面的代码。注意其中代码段的顺序,思考一下,这些代码的顺序能否互相调换,为什么?这应该对学习很有帮助的。为了演示,让所有的线程都Sleep了一段时间。
using System.Net;
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace Webb.Study
{
class TestThread
{
static Mutex m_Mutex = new Mutex();
static Thread[] m_testThreads = new Thread[10];
static int m_threadIndex = 0;
static void ThreadCallBack()
{
TestThread.m_Mutex.WaitOne();
&nbs......
使用.NET访问 Internet(1) Paul_Ni(原作)(2006-08-03 11:03:00)
摘要:Microsoft .NET 框架提供 Internet 服务的分层的、可扩展的和托管的实现,您可以将这些 Internet 服务快速而轻松地集成到您的应用程序中。您的应用程序可建立在可插接式协议的基础之上以便自动利用新的 Internet 协议,或者它们可以使用 Windows 套接字接口的托管实现来使用套接字级别上的网络。
介绍可插接式协议
Microsoft .NET 框架提供分层的、可扩展的和托管的 Internet 服务实现,您可以将它们快速而轻松地集成到您的应用程序中。System.Net 和 System.Net.Sockets 命名空间中的 Internet 访问类可用于实现基于 Web 和基于 Internet 的应用程序。
Internet 应用程序
Internet 应用程序大体上分为两类:客户端应用程序(请求信息)和服务器应用程序(响应来自客户端的信息请求)。典型的 Internet 客户端-服务器应用程序是万维网 (World Wide Web),在万维网中,人们使用浏览器来访问世界各地的 Web 服务器上存储的文档和其他数据。
应用程序并不限于仅充当其中的一个角色;例如,大家所熟悉的中间层应用程序服务器通过请求其他服务器的数据来响应客户端的请求,在这种情况中,它既作为服务器,也作为客户端。
客户端应用程序通过标识所请求的 Internet 资源以及用于该请求和响应的通讯协议来发出请求。如有必要,客户端还提供完成请求所需的任何附加数据,例如代理位置或身份验证信息(用户名、密码等)。只要构成了请求,就可以将该请求发送到服务器。
标识资源
.NET 框架使用统一资源标识符 (URI) 来标识所请求的 Internet 资源和通讯协议。URI 至少由三个(也可能是四个)片段组成:方案标识符(标识用于请求和响应的通讯协议)、服务器标识符(由域名系统 (DNS) 主机名或 TCP 地址组成,用于唯一标识 Internet 上的服务器)、路径标识符(定位服务器上请求的信息)以及可选的查询字符串(将信息从客户端传送到服务器)。例如,URI“http://www.contoso.com/whatsnew.aspx?date=today”就是由方案标识符“http”、服务器标识符“www.contoso.com”、路......
SQL server阻塞(来自微软技术支持人员)(2006-07-25 14:17:00)
摘要:阻塞定义
===============
当来自应用程序的第一个连接控制锁而第二个连接需要相冲突的锁类型时,将发生阻塞。其结果是强制第二个连接等待,而在第一个连接上阻塞。不管是来自同一应用程序还是另外一台客户机上单独的应用程序,一个连接都可以阻塞另一个连接。
说明 一些需要锁保护的操作可能不明显,例如系统目录表和索引上的锁。
大多数阻塞问题的发生是因为一个进程控制锁的时间过长,导致阻塞的进程链都在其它进程上等待锁。
常见的阻塞情形包括
===============
1 .提交执行时间长的查询。
长时间运行的查询会阻塞其它查询。例如,影响很多行的 DELETE 或 UPDATE
操作能获取很多锁,这些锁不论是否升级到表锁都阻塞其它查询。因此,一般不要将长时间运行的决策支持查询和联机事务处理 (OLTP)
查询混在一起。解决方案是想办法优化查询,如更改索引、将大的复杂查询分成简单的查询或在空闲时间或单独的计算机上运行查询。
2 .查询不适当地使用游标。游标可能是在结果集中浏览的便利方法,但使用游标可能比使用面向集合的查询慢。
3 .取消没有提交或回滚的查询。
如果应用程序取消查询(如使用开放式数据库连接 (ODBC) sqlcancel 函数)但没有同时发出所需数目的 ROLLBACK 和 COMMIT
语句,则会发生这种情况。取消查询并不自动回滚或提交事务。取消查询后,所有在事务内获取的锁都将保留。应用程序必须提交或回滚已取消的事务,从而正确地管理事务嵌套级。
4 .应用程序没处理完所有结果。
将查询发送到服务器后,所有应用程序必须立即完成提取所有结果行。如果应用程序没有提取所有结果行,锁可能会留在表上而阻塞其他用户。如果使用的应用程序将
Transact-SQL 语句透明地提交给服务器,则该应用程序必须提取所有结果行。如果应用程序没这样做(如果无法配置它执行此操作),则可能无法解决阻塞问题。为避免此问题,可以将这些应用程序限制在报表或决策支持数据库上。
5 .分布式客户端/服务器死锁。
与常规死锁不同,分布式死锁无法由 Microso......
SQL SERVER 2000中如何让union all构造出来的视图(view(2006-07-24 14:46:00)
摘要:当我们把几个表的某些字段抽取出来,然后用union all创建出一个view时,我们总希望这些表的索引能够在针对视图的查询时有效。很久以前,我凭着对sql server的SQL自动优化的超级相信,想当然地以为它能够做到这点。但是sql2000让我失望并且痛苦了一回。
假设我们有这样的两个表
X(a,b) Y(a)
在X上有分别针对a和b建立的索引IX_X_a,和IX_X_b,在Y上有索引IX_Y_a
接下来我们构造一个这样的 view(V)
select a,b from X
union all
select a,a from Y
然后我们对这样的两个查询进行分析:
1、select * from V where a = @s
2、select * from V where b = @s
看看执行计划,发现什么了吗? 对,在查询2中很悲惨地对Y表进行了全表扫描! 当Y表的数据越来越大,这个查询的速度就会越来越慢,缺少SEEK的下场可想而知。而据说,这个问题在sql2005中得到了解决,我们只能对现在仍不敢使用的2005再多一份期盼了。
那么在2000中我们无法去解决这个问题呢,放弃使用view?不行,这个view被大量多次地使用。使用分区视图?也不行,分区视图指的是这些用到的字段必须是相同。其实分区视图和2005的分区表是有些类似的。而此场景下的X,Y表完全是两个不同的东西(实际上X还有很多列,Y也还有很多列)。
我的解决方法就是对Y表增加一个b列,让它的值等于a,首当其冲的就是使用计算列了,formula为[a],再对视图查询看看,OK了,两个索引都会被利用到了。但是问题还是有的,在接下来的合并复制(Merge Replication)中,我遇到了意料不到的错误(此是后话,按下不表)!!! 所以我现在使用了trigger来做这件事,在insert时update b = a。
除了复制,这个视图仍然不够聪明,我实际上的视图大概是这样的:
select 'X' as type,a,b from X
union all
select 'Y' as type,a,b from Y
当我使用查询如下时
select * from V where type = '......
我需要什么样的ORM(对象持久层)(2006-07-24 14:32:00)
摘要:首先声明,标题中是“我”,不是“我们”,别人希望如何我不太能够帮着下结论。
一个可以打动我的持久化层(Persistence Layer)或者说OR/M(Object Relateion Mapping)应该具备哪些特征呢?
1、简单,尽可能地简单
没必要为了我偶尔用到的功能花费太多的精力,CRUD满足之后,关于Relation如何处理的问题,我觉得尽可以不必那么讲究,一定要那么OO吗? 一定要 order.items这样去访问order的明细吗? 我觉得太可不必,为了实现这种功能,一是我必须再设计Entity类,以决定有哪些OnetoOne、OnetoMany, ManytoMany的关系,然后会定义一个类似这样的很OO的class出来:
class order
{
.....
customer _customer;
entitylist _items;
}
看上去真的很帅,但是我必须去维护它,因为不是所有的关系都需要这样定义,lazy loading并不能让人就可以放肆地定义一个很“胖”的类出来。
如果有人说我可以先class,再使用schema工具生成数据库,那么很不幸,我们没有共同语言了,起码我现在对这种方式不感兴趣,而且我也从来不这样做,像如何让union all构造出来的view利用到索引里所说的一样,我会因为数据库增加一些不相关的列,也会因为性能而再增设冗余,用class的方式去思考的话,我很难知道最终的数据库要做多少修改。如果仍然用“表”的方式去先构建“类”,那么我觉得这是一种掩耳盗铃的行为。顺便说一句,我暂时对domain object还不是很感兴趣。entity就是用来存储数据的,其它的事千万别让它去承担。
那么我希望如何处理relation呢? 非常简单:
entitylist items = pl.getList(order, typeof(orderline));
那么如何生成filter呢? 命名规则+代码生成,用order的主键id的值,以及用orderline的order_id列,构造select ... from orderline where order_id = order.id
2、......
Refactoring Patterns: 第二部分(2006-07-24 14:21:00)
摘要:为什么要去改变已经可以正确运行的软件?这样的改变是否影响到我们的设计,从而进一步改变我们对于面向对象系统进行设计的方法和思路?本部分试图回答这些问题。
Refactoring虽然需要更多的"额外工作",但是它给我们带来的各种好处显然值得我们做出这样的努力:
简化测试
一个好的Refactoring实现能够减少对新设计的测试量.因为Refactoring的每一步都保持可观察的行为,也就是保持系统的所有单元测试都能顺利通过。所以只有发生改变的代码需要测试.这种增量测试使得所有的后续测试都建立在坚实的基础之上,整个系统测试的复杂性大大降低。
回页首
更简单的设计
Refactoring降低初始设计的复杂程度.Gamma指出复杂设计模式的一个陷阱是过度狂热:"模式有其成本(间接性、复杂化),因此设计应该达到需求所要求的灵活性,而不是越灵活越好"。如果设计试图介入太多以后可能需要的灵活性,就会产生不必要的复杂和错误。Refactoring能够以多种方式扩展设计。他鼓励为手头的任务建立刚刚合适的解决方案,当新的需求来到时,可以通过Refactoring扩展设计。
回页首
Refactoring增进软件可理解性
程序的最终目的是为了指引计算机完成人们需要完成的事情。但是,要完成这个目标并非想象的那么容易。
程序编写是人的活动,人首先要理解才能行动。所以,源代码的另一个作用就是用于交流的工具。其他人可能会在几个月之后修改你的代码,如果连理解你的代码都做不到,他又如何完成所需的修改呢?我们通常会忘掉源代码的这种用处,尽管它可能是源代码更重要的用处。不然,我们为什么发展高级语言、面向对象语言,为什么我们不直接使用汇编语言甚至是机器语言来编写程序?难道我们真的在意计算机多花了几个CPU周期去完成一件事?
如果一个人能够理解我们的代码,他可能只需要一天的时间完成一个增加功能的任务,而如果他不理解我们的代码,可能需要花上一个礼拜或更长的时间。这里的问题是,我们在编写代码的时候不但需要考虑计算机CPU的想法,更要把以后的开发者放在心上。除非,你写代码的唯一目的就是把它丢掉。你不想让......
Refactoring Patterns: 第三部分(2006-07-24 14:20:00)
摘要:任何一种技术都可能有它自己的麻烦。但是往往在我们使用一种新技术的时候,可能还不能深入到发现它带来的问题,正如Martin Fowler所说:
在学习一种能够极大提高生产力的新技术时,你很难看到它不能应用的场合。
他把Refactoring的情景和面向对象出现使得情景相比较:
情况恰如10年前的对象。不是我不考虑对象有限制。只是因为我不知道那些限制是什么,虽然我知道他带来的好处。
但是Martin Fowler和其他人确实观察到了Refactoring可能引发的某些问题,我们可以来看一下:
数据库
很多应用程序的代码可能与数据库结构绑定得非常严密。如果要修改这些代码,需要改变还有数据库结构和原先已经存在的数据。
O/R mapping可以用来解决这个问题。使用专业的O/R mapping工具能够实现关系数据库的迁移。但是,就算这样,迁移也需要付出额外的代价。
如果你使用的并非关系数据库,而是直接采用OO数据库,这一点的影响可能会变得更小。
所以,我建议每一个使用数据库的应用程序都应该采用O/R mapping或者OO数据库。目前出现的各种企业级应用解决方案如J2EE本身就提供这样的构架。
如果你的代码没有这样一个隔离层,那么你必须手工或编写专用的代码来实现这些迁移功能。
回页首
接口改变和Published Interface
有很多Refactoring操作(如rename method name)确实改变了接口。面向对象承诺在接口不变的情况下给你以实现变化的自由。但如果接口发生改变,那么你就不得不非常小心了。
为了保证系统的可观察行为不变,你必须保证这些接口的改变不会影响到你无法取得的代码。如果你拥有了所有使用该接口的类的源代码,你只要把这些地方同时也改变即可。
但是,如果你没有办法得到所有这些使用的代码,那么你就不得不采取额外的途径。事实上,如果你的代码是一个代码库(如Sun JDK的集合框架)或者是一个Framework,那么这一点几乎是不可避免的。
要使得这些依赖于你老接口的代码能够继续工作,你必须保留老接口。现在你有两套接口,一套是老的,一套是经过Refactoring的新接口。你必须把对老接口的调用分派到新接口......
Hibernate --什么是ORM(对像/关系映射)(2006-07-24 14:13:00)
摘要:也许你听说过Hibernate的大名,但可能一直不了解它,也许你一直渴望使用它进行开发,那么本文正是你所需要的!在本文中,我向大家重点介绍Hibernate的核心API调用库,并讲解一下它的基本配置。
看完本文后,我相信你对什么是ORM(对像/关系映射)以及它的优点会有一个深刻的认识,我们先通过一个简单的例子开始来展现它的威力。
正如一些传统的经典计算机文章大都会通过一个“hello,world”的例子开始讲解一样,我们也不例外,我们也将从一个相对简单的例子来阐述Hibernate的开发方法,但如果要真正阐述Hibernate的一些重要思想,仅仅靠在屏幕上打印一些字符是远远不够的,在我们的示例程序中,我们将创建一些对象,并将其保存在数据库中,然后对它们进行更新和查询。
“Hello World”
Hibernate应用程序定义了一些持久类,并且定义了这些类与数据库表格的映射关系。在我们这个“Hello world”示例程序中包含了一个类和一个映射文件。让我们看看这个简单的持久类包含有一些什么?映射文件是怎样定义的?另外,我们该怎样用Hibernate来操作这个持久类。
我们这个简单示例程序的目的是将一些持久类存储在数据库中,然后从数据库取出来,并将其信息正文显示给用户。其中Message正是一个简单的持久类:,它包含我们要显示的信息,其源代码如下:
列表1 Message.Java 一个简单的持久类
package hello;
public class Message {
private Long id;
private String text;
private Message nextMessage;
private Message() {}
public Message(String text) {
this.text = text;
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
什么是持久化和对象关系映射ORM技术(2006-07-24 13:45:00)
摘要:何谓“持久化”
持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
何谓“持久层”
持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。
何谓“对象数据映射(ORM)”
ORM-Object/Relational Mapper,即“对象-关系型数据映射组件”。对于O/R,即 Object(对象)和 Relational(关系型数据),表示必须同时使用面向对象和关系型数据进行开发。
备注:建模领域中的 ORM 为 Object/Role Modeling(对象角色建模)。另外这里是“O/R Mapper”而非“O/R Mapping”。相对来讲,O/R Mapping 描述的是一种设计思想或者实现机制,而 O/R Mapper指以O/R原理设计的持久化框架(Framework),包括 O/R机制还有 SQL自生成,事务处理,Cache管理等。
除了 ORM 技术,还有以下几种持久化技术
主动域对象模式
它是在实现中封装了关系数据模型和数据访问细节的一种形式。在 J2EE 架构中,EJB 组件分为会话 EJB 和实体 EJB。会话 EJB 通常实现业务逻辑,而实体 EJB 表示业务实体。实体 EJB 又分为两种:由 EJB 本身管理持久化,即 BMP(Bean-Managed Persistence);有 EJB 容器管理持久化,即 CMP(Container-Managed Persistence)。BM P就是主动域对象模式的一个例子,BMP 表示由实体 EJB 自身管理数据访问细节。
主动域对象本身位于业务逻辑层,因此采用主动域对象模式时,整个应用仍然是三层应用结构,并没有从业务逻辑层分离出独立的持久化层。
JDO 模式
Java Data Objects(JDO)是 SUN 公司制定的描述对象持久化语义的标准API。严格的说,JDO 并不是对象-关系映射接口,因为它支持把对象持久化到任意一种存储系统中,包括 关系数据库、面向对象的数据库、基于 XML 的数据库,以及其他专......
慎用const关键字(2006-07-24 13:39:00)
摘要: 我们在coding的时候,经常会做一个Config类,里面定义一些系统的公用变量。
可能里面会出现这样的代码:
public const string PBD_Sys = @"……"; 也有可能会有人写成这样的样子:
public static readonly string TempUnZipFilePath = "NewVersion"; 那么,这两种方式究竟有哪些不同呢?一个是采用的const,一个采用static readonly。
这个涉及到一点编译器的工作方式。比如说,上面的代码出现在类config中,config所在的project,我们命名为A。我们在projectB中调用projectA,这个时候,const和static readonly就会有一些小小的区别,有的时候,这个小小的区别,就会造成一个重大的bug
代码如下(Project A中):
public class Config
{
public const string PBDSys = "PDB";
public static readonly string&nbs......