如何正确结束Java线程

如何正确结束Java线程,第1张

1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

2. 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。

3. 使用interrupt方法中断线程。

1. 使用退出标志终止李团线程

当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。

package chapter2

public class ThreadFlag extends Thread

{

public volatile boolean exit = false

public void run()

{

while (!exit)

}

public static void main(String[] args) throws Exception

{

ThreadFlag thread = new ThreadFlag()

thread.start()

sleep(5000)// 主线程延迟5秒

thread.exit = true // 终止线程thread

thread.join()

System.out.println("线程退出!")

}

}

在上面代码盯扰没中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值,

2. 使用stop方法终止线程

使用stop方法可以强行终止正在运行或挂起的凯纳线程。我们可以使用如下的代码来终止线程:

thread.stop()

虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。

3. 使用interrupt方法终止线程

使用interrupt方法来终端线程可分为两种情况:

(1)线程处于阻塞状态,如使用了sleep方法。

(2)使用while(!isInterrupted()){……}来判断线程是否被中断。

在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException例外,而在第二种情况下线程将直接退出。下面的代码演示了在第一种情况下使用interrupt方法。

package chapter2

public class ThreadInterrupt extends Thread

{

public void run()

{

try

{

sleep(50000) // 延迟50秒

}

catch (InterruptedException e)

{

System.out.println(e.getMessage())

}

}

public static void main(String[] args) throws Exception

{

Thread thread = new ThreadInterrupt()

thread.start()

System.out.println("在50秒之内按任意键中断线程!")

System.in.read()

thread.interrupt()

thread.join()

System.out.println("线程已经退出!")

}

}

上面代码的运行结果如下:

在50秒之内按任意键中断线程!

sleep interrupted

线程已经退出!

在调用interrupt方法后, sleep方法抛出异常,然后输出错误信息:sleep interrupted.

注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断。因此,while (!isInterrupted())也可以换成while (!Thread.interrupted())。

关于消息循环:

1,我们站在一个什么高度看消息循环?消息循环其实没有什么深奥的道理。如果一个邮递员要不断在一个城市中送信,我们要求他做什么?要求他来回跑,但他一次只能在一个地方出现。如果我们的应用程序只有一个线程的话,我们要他不断地为窗口传递消息,我们怎么做?在一个循环中不断的检测消息,并将他发送到适当的窗口。窗口可以有很多个,但消息循环只有一个,而且每时每刻最多只有一个地方在执行代码。为什么? 看第二点。

2,因为是单线程的(程序进程启动的时候,只有而且有一个线程,我们称他为主线程),所以就像邮递员一样,每次只能在某一个地方干活。什么意思呢?举个例子,用::DiapatchMessage派送消息,在窗口处理过橘冲清程(WinProc,窗口函数)返回之前,他是阻塞的,不会立即返回,也就是消息循环此时不能再从消息队列中读取消息,直到::DispatchMessage返回。如果你在窗口函数中执行一个死循环 *** 作,就算你用PostQuitMessage函数退出,程序也会down掉。

while(1)

{

PostQuitMessage(0)//程序照样down.

}

所以,当窗口函数处理没有返回的时候,消息循环是不会从消息队列中读取消息的。这也是为什么在模式对话框中要自己用无限循环来继续消息循环,因为这个无限循环阻塞了原来的消息循环,所以,在这个无限循环中要用GetMessage,PeekMessage,DispatchMessage来从消息队列中读取消息并派送消息了。要不然程序就不会响应了,这不是我们所希望的。

以说,消息循环放在程序的什么的地方都基本上是过的去的,比如放在DLL里面。但是,最好在任何时候,只有一个消息循环在工作(其他的都被阻塞了)。然后,我们要作好的一件事情,就是怎么从消息循环中退出!当然用WM_QUIT是可以拉~(PostThreadMessage也是个好主意),这个消息循环退出后,可能程序退出,也可能会激活另外一个被阻塞的消息循环,程序继续运行。这要看你怎么想,怎么去做。最后一个消息循环结束的时候,也许就是程序快结束的时候,因为主线程的执行代码也快要完了(除非BT的再作个死循环)。

NOTE: 让windows系统知道创建一个线程的唯一方法是调用API CreatThread函数(__beginthreadex之类的都要在内部调用他创建新线程)。好像windows核心编程说,在win2000下,系统用CreateRemoteThread函数来创建线程,CreateThread在内部调用CreateRemoteThread。不过这不是争论的焦点,至少win98下CreateRemoteThread并不能正常工作,还是CreateThread主持大局。

3,在整个消息循环的机制中,还必须谈到窗口函数的可重入性。什么意思?就是窗口函数(他是个回调函数)的代码什么时候都可以被系统(调用者一般是user32模块)调用。比如在窗口过程中,向自己的窗口SendMessage(***)那么执行过程是怎样的?

我们知道,SendMessage是要等到消息发送并被目标窗口执行完之后才返圆前回的。那么窗口在处理消息,然后又等待刚才发送到本窗口的消息被处理后之后(SendMessage返回)才继续往下执行,程序不就互相死锁了吗?

其实是不会的。windows设计一套适合SendMessage的判则算法,他判断如果发送的消息是属于本线程创建的窗口的,那么直接由user32模块调用窗口函数(可能就有窗口重入),并将消息的处理结果结果返回。这样做体现了窗口重入。上面的例子,我们调用SendMessage(***)发送消息到本窗口,那么窗口过程再次被调用,处理完消息之后将结果返回,然后SendMessage之后的程序接着执行。对于非队列消息,如果没有窗口重入,不知道会是什么样子。

NOTE: 由于窗口的可重入性。在win32 SDK程序中应尽量少用全局变量和静态变量,因为在窗口函数执行过程中可能窗口重入,如果重入后将这些变量改了,但你的程序在窗口重入返回之后继续执行,可能就是使用已经改变的全局或静态变量。在MFC中(所有窗口的窗口函数基本上都是AfxWndProc),按照类的思想进行了组织,一般变量都是类中的,好管理的多。

4,MFC中窗口类(比如C**View,CFrameWnd等)中的MessageBox函数,以及AfxMessageBox函数都是阻塞原有的消息循环的。由消息框内部的一个消息循环来从消息队列中读取消息,并派送消息(和模式对话框类似)。实际上,这些消息函数最终调用的是::MessageBox,它在消息框内部实现了一个消息循环(原有的主程序消息循环被阻塞了)。论坛中碰到过几次关于计时器和消息框的问题,看下面的代码:

void CTest_recalclayoutView::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

MessageBox("abc")

while(1)//设计一个死循环

CView::OnTimer(nIDEvent)

}

咱让OnTimer大约5秒钟d出一个消息框。那么,消息框不断的被d出来,只要消息框不被关闭,那么程序就不会进入死循环。实际上,每次d出对话框,都是最上层的那个消息框掌握着消息循环,其他的消息循环被阻塞了。只要不关闭最上面的消息框,while(1)就得不到执行。如果点了关闭,程序就进入了死循环,只能用ctrl+alt+del来解决问题了。

5,消息循环在很多地方都有应用。比如应用在线程池中。一个线程的执行周期一般在线程函数返回之后结束,那么怎么延长线程的生命周期呢?一种方法就是按照消息循环的思想,在线程中加入消息循环,不断地从线程队列读取消息,并处理消息,线程的生命周期就保持着直到这个消息循环的退出。

NOTE:只要线程有界面元素或者调用GetMessage,或者有线程消息发送过来,系统就会为线程创建一个消息队列。

6,在单线程程序中,如果要执行一个长时间的复杂 *** 作而且界面要有相应的话,可以考虑用自己的消息泵。比如,可以将一个阻塞等待 *** 作放在一个循环中,并将超时值设置得比较小,然后每个等待的片段中用消息泵继续消息循环,使界面能够响应用户 *** 作。等等之类,都可以应用消息泵(调用一个类似这样的函数):

BOOL CChildView::PeekAndPump()

{

MSG msg

while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))

{

if(!AfxGetApp()->PumpMessage())

{

::PostQuitMessage(0)

return false

}

}

return true

}

其实,用多线程也能解决复杂运算时的界面问题,但是没有这么方便,而且一般要加入线程通信和同步,考虑的事情更多一点。

综上所述,MFC消息循环就那么回事,主要思想还是和SDK中差不多。这种思想主要的特点表现在迎合MFC整个框架上,为整个框架服务,为应用和功能服务。

首先给出XML文件(telephone.xml,unicode格式)的定义:

<?xml version="1.0" ?>

<telephones>

<telephone name="铜化金" telephonen="(020)845559887" email="[email protected]" />

<telephone name="全不真" telephonen="(020)842342444" email="[email protected]" />

</telephones>

<?xml version="1.0" ?><telephones><telephone name="铜化金" telephonen="(020)845559887" email="[email protected]" /><telephone name="全不真" telephonen="(020)842342444" email="[email protected]" /></telephones>

铜化金,全不真.哈,都是假的!但不会影响我们的研究.先看看连接XML过程:

var myXML = new XML()// 建立一个XML对象

myXML.ignoreWhite = true// 放弃仅包含空白的文本节点

myXML.onLoad = function(success) {

//trace("xml file loaded!")// 测试点1

if (success) {

parseXML(this)// 若加载XML成功,执行parseXML函数

}

}

myXML.load("telephone.xml")// 加载本棚大谨地XML文件

function parseXML(xmlDoc) {

// 这里写加载成功之后的语句,如读取/写入XML

}

var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { //trace("xml file loaded!")// 测试点1 if (success) { parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 function parseXML(xmlDoc) { // 这里写加载成功之链基后的语句,如读取/写入XML }

这个加载过程是比较完善的.看看随便给出的测试函数:

// 这里写加载成功之后的语句,如读取/写入XML

var nm = xmlDoc.firstChild.childNodes

trace(nm[0].attributes.name)// 测试点2

// 这里写加载成功之后的语句,如读取/写入XML var nm = xmlDoc.firstChild.childNodestrace(nm[0].attributes.name)// 测试点2

看,打印出"铜化金"来了.主要要讲是是第一句:

nm是个数组,您可以明确表明它是一个数组.如:

// 这里写加载成功之后的语句,如读取/写入XML

var nm:Array = new Array()

nm = xmlDoc.firstChild.childNodes

trace(nm[0].attributes.name)

// 这里写加载成功之后的语句,如读取/写入XML var nm:Array = new Array()nm = xmlDoc.firstChild.childNodestrace(nm[0].attributes.name)

这是标准写法,显得累赘一点.而xmlDoc是函数参数传入的XML对象.(这里也可用myXML)

firstChild就是引用父级节点的子级列表中的第一个子级(若没,则为null),这里就是指向<telephones>.childNodes则是此子级的所有子级组成的数组.

还不明显吗? 就是把所有telephone记录赋予给nm数组!然后就可以在nm数组里读取数据了!

还是让我们来做一个实际项目,在fla文件中放三个动态文本输入框,实例名仿庆字分别是t1,t2,t3.分别用来存储姓名,电话号码,电子邮箱地址.您可以在这三个动态文本前加上提示,这里就不详述了.

然后添加两个Button组件,其label属性分别是Perv,Next.实例名字分别是b1,b2

改写程序,如下:

var myXML = new XML()// 建立一个XML对象

myXML.ignoreWhite = true// 放弃仅包含空白的文本节点

myXML.onLoad = function(success) {

if (success) {

//trace("xml file loaded!")

parseXML(this)// 若加载XML成功,执行parseXML函数

}

}

myXML.load("telephone.xml")// 加载本地XML文件

var n:Number = new Number(0)// 建立保存当前节点变量

function parseXML(xmlDoc) {

// 这里写加载成功之后的语句,如读取/写入XML

display(0)

}

function display(n)

{

var nm:Array = new Array()

nm = myXML.firstChild.childNodes

t1.text = nm[n].attributes.name

t2.text = nm[n].attributes.telephonen

t3.text = nm[n].attributes.email

}

stop()

var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { if (success) { //trace("xml file loaded!")parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 var n:Number = new Number(0)// 建立保存当前节点变量 function parseXML(xmlDoc) { // 这里写加载成功之后的语句,如读取/写入XML display(0)} function display(n) { var nm:Array = new Array()nm = myXML.firstChild.childNodest1.text = nm[n].attributes.namet2.text = nm[n].attributes.telephonent3.text = nm[n].attributes.email } stop()

b1中写:

on(click)

{

_root.n = _root.n - 1

_root.display(_root.n)

}

on(click) { _root.n = _root.n - 1_root.display(_root.n)}

b2中写:

on(click)

{

_root.n = _root.n + 1

_root.display(_root.n)

}

on(click) { _root.n = _root.n + 1_root.display(_root.n)}

虽然没有强检测返回的数据(超出了文件显示undefined),但已经实现了基本的数据控制了。其实我们可以很容易完善它,看:

var myXML = new XML()// 建立一个XML对象

myXML.ignoreWhite = true// 放弃仅包含空白的文本节点

myXML.onLoad = function(success) {

if (success) {

//trace("xml file loaded!")

parseXML(this)// 若加载XML成功,执行parseXML函数

}

}

myXML.load("telephone.xml")// 加载本地XML文件

var n:Number = new Number(0)// 建立保存当前节点变量

var nMax:Number = new Number(0)// 建立保存最大子级变量

function parseXML(xmlDoc) {

// 这里写加载成功之后的语句,如读取/写入XML

display(0)

}

function display(n)

{

var nm:Array = new Array()

nm = myXML.firstChild.childNodes

nMax = nm.length -1

t1.text = nm[n].attributes.name

t2.text = nm[n].attributes.telephonen

t3.text = nm[n].attributes.email

}

stop()

var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { if (success) { //trace("xml file loaded!")parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 var n:Number = new Number(0)// 建立保存当前节点变量 var nMax:Number = new Number(0)// 建立保存最大子级变量 function parseXML(xmlDoc) { // 这里写加载成功之后的语句,如读取/写入XML display(0)} function display(n) { var nm:Array = new Array()nm = myXML.firstChild.childNodesnMax = nm.length -1 t1.text = nm[n].attributes.namet2.text = nm[n].attributes.telephonent3.text = nm[n].attributes.email } stop()

b1的定义:

on(click)

{

if(_root.n <_root.nMax){

_root.n = _root.n + 1

_root.display(_root.n)

}

}

on(click) { if(_root.n <_root.nMax){ _root.n = _root.n + 1_root.display(_root.n)} }

b2的定义:

on(click)

{

if(_root.n>0) {

_root.n = _root.n - 1

_root.display(_root.n)

}

}

on(click) { if(_root.n>0) { _root.n = _root.n - 1_root.display(_root.n)} }

看得出来那里改过吗?(其实加粗文字的地方就是了).看看我做的效果吧(丑陋得很,好在不是做美工的"心得体会")

Flash MX Professional 2003中没有向xml文件增加数据的功能.即保存文件,Flash是没有这个能力,但创建节点当然还是可以:

var xmlDoc = new XML()

var root = xmlDoc.createElement("abc")

xmlDoc.appendChild(root)

var child0 = xmlDoc.createElement("def")

root.appendChild(child0)

trace(xmlDoc)

var xmlDoc = new XML()var root = xmlDoc.createElement("abc")xmlDoc.appendChild(root)var child0 = xmlDoc.createElement("def")root.appendChild(child0)trace(xmlDoc)

至于如何保存XML文件,可以使用诸如ASP等语言的协助.但这样比较麻烦了,本文不涉及这点.(我会写一个笔记,关于如何保存XML的.请关注BLOG安排)

XML入门必看(建议中等Flash学习者观看)

一、有关XML

1、XML入门知识

XML(eXtensible Markup Language)是一种具有数据描述功能(Meta-language)、高度结构性及可验证性的语言。和HTML一样,XML同样使用了标记和属性;和HTML最大的不同在于XML的标记和属性允许用户自行定义,并可以依照所定义的标记与属性的语法来开发应用程序。XML采用了开放架构设计,它允许在Internet上的任何平台或语言之间交换数据。这项技术已经被广泛采用,目前几乎难以找到一个不以某种方式使用XML的应用程序。

一个简单的XML文件如下所示:

<XML>

<FLASH>

<A1>XML入门知识</A1>

<A2>撰写XML</A2>

</FLASH>

<OTHER>

<A1>为什么是XML</A1>

</OTHER>

</XML>

在Flash中涉及的XML不会很复杂,能看懂类似上面这样的XML文件,足已对付。

2、为什么在Flash中用XML

首先,大多数浏览器限制了URL为256个字符(包括查询字符串数据)。而XML对象没有这样的限制,这就使它成为将数据库内容加入Flash动画的一个理想方法。

其次,XML对象允许输入和集成任何Web上的XML格式的数据到Flash中,Flash能够将XML数据和精彩的动画及声音无缝结合起来。

另外,Flash几乎拥有在任何平台上处理XML的能力。一般来说,大多数XML转换是在服务器端处理的,因为浏览器对XML的支持不是很完全。

但是,Flash载入一个外部XML文件如果超过15秒就会超时,它不会再进行载入,Flash Player和动画会停止。同样的,在浏览器中使用load或sendAndLoad载入64K或更大的数据会导致性能问题。其特征包括服务器应答"Error 501-Not Implemented"或浏览器的无响应状态。Flash Player也不能从外部Web站点上载入XML文件。Flash动画只能从它自己的域里载入XML数据。例如,一个在adomain.com上的Flash动画就不能从bdomain.com读取或载入XML数据。

二、Flash中XML应用的原理

从Flash MX开始,对XML的支持已经初具规模,在Flash MX 2004中得到了加强,现在用Flash MX 2004来做有关XML的应用已经很方便了。在Flash MX 2004中使用XML主要有两种方式,使用XML对象和使用XMLSocket对象。使用XML对象应用的是HTTP的通讯方式,而使用XMLSocket对象应用的是Socket的通讯方式,两者有比较大的区别。

下面分别介绍使用XML的两种方式。

1、使用XML对象

在网络应用中,使用XML对象应用HTTP的通讯方式,基本的通讯模式仍然是请求响应。先在Flash中对数据进行处理,生成XML树,然后通过HTTP的通讯方式将XML文件发送到服务器端。在服务器端,先对接收到的XML树进行解释,再根据流程做相应的 *** 作,比如读写数据库或其他的资源,然后生成XML树,通过HTTP的通讯方式将XML文件发送到Flash端。最后在Flash端接收XML文件,对XML树进行解释,对相应的数据进行 *** 作,如此循环。其通讯原理请参考图1。

下面分别介绍Flash端和服务器端的东西。

A、Flash端:主要用到XML对象中的send()、load()、sendAndLoad()、onLoad()、onData()及其他 *** 纵XML树的方法与事件。

比如,生成XML树的代码如下:

loginXML = new XML()//生成一个XML对象

loginElement = loginXML.createElement("LOGIN")//生成一个元素

loginElement.attributes.username = username//设置元素的属性

loginElement.attributes.password = password

loginXML.appendChild(loginElement)//将所生成的元素加到XML对象

解释XML树的代码如下:

loginReplyXML = new XML()//生成一个响应的XML对象

loginReplyXML.onLoad = onLoginReply()//设置响应XML对象下载事件的函数

function onLoginReply () { //对返回的XML文件进行 *** 作

var e = this.firstChild//解释返回的XML文件

if (e.nodeName == "LOGINREPLY" &&e.attributes.status == "OK") {

//根据返回的XML文件中的数据做相应的 *** 作

gotoAndStop ("success")

} else {

gotoAndStop ("loginFailed")

}}

有关XML数据的通讯代码如下:

loginXML.sendAndLoad("http://www.pcedu.com.cn/test.asp", loginReplyXML)

//根据URL去取响应的XML文件到响应的XML对象中

B、在服务器端:常用的工具有Asp、jsp、PHP、Perl等等脚本语言,它们所起的作用是 *** 纵XML树和数据的通讯。

下面以常用的Asp为例,解释XML树的代码为:

//创建一个新的Domdocument对象,存客户端传送过来的XML请求

var xmlLogin = new ActiveXObject("Msxml2.Domdocument")

//从发送来的表单中取得数据

xmlLogin.loadXML(Request.Form())

//创建XML元素

var reElement = xmlLogin.documentElement

//提取用户名和密码信息

password = reElement.attributes[0].nodevalue

username = reElement.attributes[1].nodevalue

生成XML树的代码为并发送的代码为:

//创建一个新的Domdocument对象,向客户端发送

var xmlRepley = new ActiveXObject("Msxml2.Domdocument")

//创建一个简单的XML文件

xmlRepley.loadXML("<LOGINREPLY login='1' msg='"+Msg+"' />")

//也是通过Write()的方法将XML文件返回到Flash端

Response.Write(xmlRepley.xml)

C、还有一种情况是 *** 作本地的XML文件,无非也就是生成、解释XML文件,得到所要的数据,只不过不需要在服务器端做其他的 *** 作了。比如,读一个本地的XML文件的代码为:

playlist_xml = new XML()//创建一个XML对象

playlist_xml.ignoreWhite = true//省略空白

playlist_xml.onLoad = function(success) { //当加载XML文件成功的时候触发此函数

trace("success")

}

playlist_xml.load("playlist.xml")//加载本地的XML文件

值得说明的是,上面所涉及的代码都是举例而已,实际应用中的代码可能会复杂很多。但其中的原理都是相通的,先生成XML文件,发送到服务器端,最后将服务器端返回的XML文件解释。只要思路清晰,做起来就比较有效率,也不容易出错。

2、使用XMLSocket对象

在网络通讯中,使用XMLSocket对象的通讯方式为Socket,(所谓的Socket,可以将它想象为一条通路,需要通讯的时候,在客户端跟服务器端建立一个连接,然后传送内容,通讯完毕后再撤销这个通路)。Flash端跟服务器端的通讯模式为:先在Flash端跟服务器端建立一个Socket连接,生成XML文件后,通过所建立的Socket连接将XML文件发送到服务器端,服务器端解释所接收到的文件,对数据进行相应的 *** 作后,生成一个XML文件,通过Socket连接发送到Flash端,Flash端解释XML文件后就得到所需要的数据。如此循环, *** 作完成后关闭Socket连接。有点难懂,可以参考图2仔细想想。

下面分别解释在Flash端跟服务器端的东西。

A、在Flash端:XMLSocket对象中,只有三个方法和四个事件,都是在Socket通讯时候用的,对XML文件的 *** 作还是要靠XML对象。比如,下面是一些简单的Socket *** 作:

//声明XMLSocket对象

var mySocket=new XMLSocket()

//根据IP地址和端口连接服务器

mySocket.connect("127.0.0.1",9980)

//连接成功与否的判断

mySocket.onConnect=function(sucess)else

}

//当接收到XML文档的时候,触发此函数

mySocket.onXML=function(xmlDoc)

B、在服务器端:选用服务器端的开发语言的标准是,起码要能够做Socket方面的 *** 作(复杂的应用当中还需要多线程、负载平衡等方面的东西)。比较常用的有C/C++、java,其他的比如Delphi、Vb等工具对Socket的 *** 作就有点不方便。要开发一个高效率、稳定、可扩展的服务器端程序并不是一件很简单的事情,最好能找点相应的资料深入学习一下,刚入门的时候,学习的重点可以放在Socket和多线程上面。下面以比较流行的java语言来举例说明服务器端程序的简单架构:

//运用多线程防止服务器阻塞

public class MultiThreadServer extends Thread

{

private ServerSocket listen_socket

public MultiThreadServer(int port)

{

try

{

listen_socket = new ServerSocket(port)//创建一个服务器端的Socket

this.start()//启动多线程

}

catch(IOException e) //捕捉异常

}

//下面为服务器监听线程的主程序。

public void run()

{

while(true) //死循环,一直在端口上监听有无客户端的Socket连接

{

try

{

//有客户端连接上来,创建一个相应的Socket,并启动响应的函数

Socket client_socket= listen_socket.accept()

SockState sstate=new SockState(client_socket)

OperThread oper=new OperThread(sstate)

}catch(Exception ee)

{

System.out.print("MultiThreadServer run:"+ee.getMessage())

}

}

}

}

3、XML在Flash中主要涉及两方面的应用,本地应用和网络应用。

本地应用主要是存取XML文件中所保存的数据,这里所指的数据并不一定限定是文本数据,也可以是图片数据,声音数据等等。比如可以用Flash + XML来做图片管理器,歌曲列表管理器,用处还是比较大的,也比较灵活。

网络应用是XML在Flash中的主要用途,它的优缺点在前面内容中已经提到。比如说,可以用来做电子商务方面的应用、论坛、聊天室等等。

如果看不懂,那是因为您的基础不好,您还是先去我们的初级入门板块看


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12547900.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存