Friday, January 16, 2009

.NET的垃圾回收机制

from : http://lanbaibai.blog.hexun.com/215128_d.html


近期看了看有关.net的垃圾回收方面的知识,感觉有必要将这方面的资料总结一下,和广大网友分享一下
.net的垃圾回收,借鉴了java的垃圾回收机制。在以前的windows环境下,我们实例化一个对象后,我们经常会忘记
释放掉已经无用的内存,或者试图使用已经释放掉的内存,造成程序的崩溃。但是随着.net中的垃圾回收机制出现,
这种情况得到了大大的改善。
在.net中两种变量类型,一种是值类型,一种是引用类型,值类型所占的内存,存放在当前线程的栈上,垃圾回收不负责回收这方面的内存,当前方法运行完毕后,内存会自动释放。引用类型所占的内存存放在托管堆上,.net的垃圾回收就是负责回收这方面的内存资源。
在.net中提供三种模式来回收内存资源:dispose模式,finalize方法,close方法。
·dispose提供了一种显示释放内存资源的方法。dispose调用方法是:要释放的资源对象.dispose
·finalize方法是.net的内部的一个释放内存资源的方法。这个方法不对外公开,由垃圾回收器自己调用。
·close和dispose其实一样,只不过有的对象没有提供dispose的方法,只提供了close方法,而close其实在
那个对象的类中,依然是调用了一个私有的dispose方法,而finalize其实也是调用一个不对外公开的dispose方法

那么既然.net在垃圾回收中了finalize方法,那么为什么还要提供dispose方法和close方法哪?这是因为finalize方法会释放掉托管堆内存和非托管堆内存。而dispose只会释放掉非托管的内存资源,对于托管的内存资源它不会释放,只能由垃圾回收拉释放。

当我们打开一个数据库连接的时候(这是一个非托管内存资源),如果我们不手工释放这一部分资源,
等下一次垃圾回收调用finalize方法回收资源,那么可能会是很长的时间之后,所以要使用dispose这个方法。所以当我们使用sqlconnection这个对象连接数据库后,调用sqlconnnection.dispose方法后,可以从数据库断开连接,但是sqlconnection这个对象没有消亡,这个对象可以继续使用,直到下一次垃圾回收调用finalize方法回收资源。

我们再说一下close这个方法,我们上面提到过了,它起到的作用和dispose一样。只不过有的.net有的对象没有提供dispose方法,而是用close代替,因为用close代替,比dispose显得更直观。

下面用一个例子说明finalize和dispose,close的区别。
大家看下面的代码
dim a as string="1234"
dim fs as filestream("temp.txt",fileMode,create)
fs.write(a) ''''向文件写入内容
fs.dispose() '''显示关闭文件
fs.write(a) ''''抛出错误
因为当我们调用了dispose方法,我们只是关闭了temp.txt文件,fs对象是一个托管对象,他的资源没有被释放,依然可以使用,但是
temp.txt文件已经关闭,向一个已经关闭的文件写入内容,当然会出错。
大家再看下面的代码
dim a as string="1234"
dim fs as filestream("temp.txt",fileMode,create)
dim bw as new binarywrite(fs)
bw.write(a) ''''向文件写入内容
bw.dispose() '''显示关闭文件,我们调用binarywriter.close会同时关闭filestream对象,所以不用调用fs.close方法
binarywriter接受一个filestream为对象,当我们向binarywriter对象写入数据时,其实保存在内存缓冲中,当内存缓冲写满时,binarywriter才会将数据写入文件中。
我们调用bw.dispose会导致binarywriter对象将数据填入到filestream中,同时关闭filestream对象,当filestream对象关闭,它会将缓冲区的内容填入到磁盘文件中。而如果我们没有显示的调用dispose或者close方法,垃圾回收器会先中止filestream对象,关闭文件。这样缓冲区的内容会丢失,写入失败。

将字符串转换成整数

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ChangeStringToInt
{
class Program
{
static void Main(string[] args)
{
string str = "abcdef";
Console.WriteLine( ChangeToInt(str));
}

public static int ChangeToInt(string str)
{
int tot = 0;
char[] cStr;
cStr = str.ToCharArray();
for (int i = 0; i <= cStr.GetUpperBound(0); i++)
{
tot += (int)cStr[i];
}

return tot / cStr.GetUpperBound(0);
}
}
}

“abb ddd dac cad”找出相同的每组单词,dac和cad视为相同

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;//

namespace ArrayAndArrayList
{
class Program
{
static void Main(string[] args)
{
string str = "abb ddd asd sda";
char[] cha = new char[] { ' '};
string[] strArr = str.Split(cha);
//foreach (string s in strArr)
//{
// Console.WriteLine(s);
//}
bool b = false;//不匹配
for (int i = 0; i < strArr.Length; i++)
{
b = false;
string s = strArr[i];
string sj = "";
string temp = "";
for (int j = i + 1; j < strArr.Length; j++)
{
sj = strArr[j];
temp = strArr[j];
if (s.Length == sj.Length)
{
foreach (char c in s)
{
if (sj.IndexOf(c) != -1)
{
b = true;//匹配
sj = sj.Replace(c,' ');
}
else
{
b = false;
}
}
}
}

if (b)
{
Console.WriteLine(s + " " + temp);
}
}
Console.WriteLine("********************");
}
}
}

Binary Tree二叉树

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;//

namespace ArrayAndArrayList
{
public class Node
{
public int Data;
public Node Left;
public Node Right;

public void DisplayNode()
{
Console.Write(Data+" ");
}
}

///
///
///

public class BinarySearchTree
{
public Node root;
public BinarySearchTree()
{
root = null;
}
public void Insert(int i)
{
Node newNode = new Node();
newNode.Data = i;
if (root == null)
{
root = newNode;
}
else
{
Node current = root;
Node parent;
while (true)
{
parent = current;
if (i < current.Data)
{
current = current.Left;
if (current == null)
{
parent.Left = newNode;
break;
}
}
else
{
current = current.Right;
if (current == null)
{
parent.Right = newNode;
break;
}
}

}
}
}

public void InOrder(Node theRoot)
{
if (theRoot != null)
{
InOrder(theRoot.Left);
theRoot.DisplayNode();
InOrder(theRoot.Right);
}
}

public void PreOrder(Node theRoot)
{
if (theRoot != null)
{
theRoot.DisplayNode();
PreOrder(theRoot.Left);
PreOrder(theRoot.Right);
}
}

public void PostOrder(Node theRoot)
{
if (theRoot != null)
{
PostOrder(theRoot.Left);
PostOrder(theRoot.Right);
theRoot.DisplayNode();
}
}

public void FindMin()
{
Node current = root;
while (current.Left != null)
{
current = current.Left;
}
Console.WriteLine(current.Data);
}
public void FindMax()
{
Node current = root;
while (current.Right != null)
{
current = current.Right;
}

Console.WriteLine(current.Data);
}
}

class Program
{
static void Main(string[] args)
{
BinarySearchTree nums = new BinarySearchTree();
nums.Insert(23);
nums.Insert(45);
nums.Insert(16);
nums.Insert(37);
nums.Insert(3);
nums.Insert(99);
nums.Insert(22);
nums.InOrder(nums.root);
Console.WriteLine("~~~~~~~~~~~~~~~~~~~");
nums.PreOrder(nums.root);
Console.WriteLine("~~~~~~~~~~~~~~~~~~~");
nums.PostOrder(nums.root);
Console.WriteLine("~~~~~~~~~~~~~~~~~~~");
nums.FindMin();
Console.WriteLine("~~~~~~~~~~~~~~~~~~~");
nums.FindMax();
}
}
}