??xml version="1.0" encoding="utf-8" standalone="yes"?>理论在线观看,欧美电影一二区,国产精品视频九色pornhttp://www.aygfsteel.com/oracle/category/42070.html1100111010001110 1001010010001010zh-cnWed, 21 Oct 2009 07:06:33 GMTWed, 21 Oct 2009 07:06:33 GMT60- 实战体会Java多线E编E精?/title>http://www.aygfsteel.com/oracle/archive/2009/10/21/299116.html逍遥晨空逍遥晨空Tue, 20 Oct 2009 16:06:00 GMThttp://www.aygfsteel.com/oracle/archive/2009/10/21/299116.htmlhttp://www.aygfsteel.com/oracle/comments/299116.htmlhttp://www.aygfsteel.com/oracle/archive/2009/10/21/299116.html#Feedback0http://www.aygfsteel.com/oracle/comments/commentRss/299116.htmlhttp://www.aygfsteel.com/oracle/services/trackbacks/299116.html
四项不相关的d
class myclass {
static public void main(String args[]) {
print_a_file();
manipulate_another_file();
access_database();
draw_picture_on_screen();
}
}
多个q程
在大多数操作pȝ中都可以创徏多个q程。当一个程序启动时Q它可以为即开始的每项d创徏一个进E,q允许它们同时运行。当一个程序因{待|络讉K或用戯入而被dӞ另一个程序还可以q行Q这样就增加了资源利用率。但是,按照q种方式创徏每个q程要付Z定的代hQ设|一个进E要占用相当一部分处理器时间和内存资源。而且Q大多数操作pȝ不允许进E访问其他进E的内存I间。因此,q程间的通信很不方便Qƈ且也不会它自己提供l容易的~程模型?br />
U程
U程也称型进E?(LWP)。因为线E只能在单个q程的作用域内活动,所以创建线E比创徏q程要廉价得多。这P因ؓU程允许协作和数据交换,q且在计资源方面非常廉P所以线E比q程更可取。线E需要操作系l的支持Q因此不是所有的机器都提供线E。Java ~程语言Q作为相当新的一U语aQ已线E支持与语言本n合ؓ一体,q样对U程提供了强健的支持?br />
使用 Java ~程语言实现U程
Java~程语言使多U程如此单有效,以致于某些程序员说它实际上是自然的。尽在 Java 中用线E比在其他语a中要Ҏ得多Q仍然有一些概念需要掌握。要C的一仉要的事情?main() 函数也是一个线E,q可用来做有用的工作。程序员只有在需要多个线E时才需要创建新的线E?br />
Thread c?br />
下面的代码说明了它的用法Q?br />
创徏两个新线E?br />
import java.util.*;
class TimePrinter extends Thread {
int pauseTime;
String name;
public TimePrinter(int x, String n) {
pauseTime = x;
name = n;
}
public void run() {
while(true) {
try {
System.out.println(name + “:” + new
Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
} catch(Exception e) {
System.out.println(e);
}
}
}
static public void main(String args[]) {
TimePrinter tp1 = new TimePrinter(1000, “Fast Guy”);
tp1.start();
TimePrinter tp2 = new TimePrinter(3000, “Slow Guy”);
tp2.start();
}
}
在本例中Q我们可以看C个简单的E序Q它按两个不同的旉间隔(1 U和 3 U?在屏q上昄当前旉。这是通过创徏两个新线E来完成的,包括 main() ׃个线E。但是,因ؓ有时要作为线E运行的cd能已l是某个cdơ的一部分Q所以就不能再按q种机制创徏U程。虽然在同一个类中可以实CQ意数量的接口Q但 Java ~程语言只允怸个类有一个父cR同Ӟ某些E序员避免从 Thread cd出,因ؓ它强加了cdơ。对于这U情况,p runnable 接口?br />
Runnable 接口
此接口只有一个函敎ͼrun()Q此函数必须由实C此接口的cd现。但是,p行这个类而论Q其语义与前一个示例稍有不同。我们可以用 runnable 接口改写前一个示例?不同的部分用黑体表示?
创徏两个新线E而不强加cd?br />
import java.util.*;
class TimePrinter implements Runnable {
int pauseTime;
String name;
public TimePrinter(int x, String n) {
pauseTime = x;
name = n;
}
public void run() {
while(true) {
try {
System.out.println(name + “:” + new
Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
} catch(Exception e) {
System.out.println(e);
}
}
}
static public void main(String args[]) {
Thread t1 = new Thread(new TimePrinter(1000, “Fast Guy”));
t1.start();
Thread t2 = new Thread(new TimePrinter(3000, “Slow Guy”));
t2.start();
}
}
h意,当?runnable 接口Ӟ您不能直接创建所需cȝ对象q运行它; 必须?Thread cȝ一个实例内部运行它。许多程序员更喜?runnable 接口Q因Z Thread cȝ承会强加cdơ?br />
synchronized 关键?br />
到目前ؓ止,我们看到的示例都只是以非常简单的方式来利用线E。只有最的数据,而且不会出现两个U程讉K同一个对象的情况。但是,在大多数有用的程序中Q线E之间通常有信息流。试考虑一个金融应用程序,它有一?Account 对象Q如下例中所C:
一个银行中的多Ҏ?br />
public class Account {
String holderName;
float amount;
public Account(String name, float amt) {
holderName = name;
amount = amt;
}
public void deposit(float amt) {
amount += amt;
}
public void withdraw(float amt) {
amount -= amt;
}
public float checkBalance() {
return amount;
}
}
在此代码样例中潜伏着一个错误。如果此cȝ于单U程应用E序Q不会有M问题。但是,在多U程应用E序的情况中Q不同的U程有可能同时讉K同一?Account 对象Q比如说一个联合帐L所有者在不同?ATM 上同时进行访问。在q种情况下,存入和支出就可能以这L方式发生Q一个事务被另一个事务覆盖。这U情况将是灾难性的。但是,Java ~程语言提供了一U简单的机制来防止发生这U覆盖。每个对象在q行旉有一个关联的锁。这个锁可通过为方法添加关键字 synchronized 来获得。这P修订q的 Account 对象(如下所C?不会遭受像数据损坏q样的错误:
对一个银行中的多Ҏ动进行同步处?br />
public class Account {
String holderName;
float amount;
public Account(String name, float amt) {
holderName = name;
amount = amt;
}
public synchronized void deposit(float amt) {
amount += amt;
}
public synchronized void withdraw(float amt) {
amount -= amt;
}
public float checkBalance() {
return amount;
}
}
deposit() ?withdraw() 函数都需要这个锁来进行操作,所以当一个函数运行时Q另一个函数就被阻塞。请注意Q?checkBalance() 未作更改Q它严格是一个读函数。因?checkBalance() 未作同步处理Q所以Q何其他方法都不会d它,它也不会dM其他ҎQ不那些方法是否进行了同步处理?br />
Java ~程语言中的高多线E支?br />
U程l?br />
U程是被个别创徏的,但可以将它们归类到线E组中,以便于调试和监视。只能在创徏U程的同时将它与一个线E组相关联。在使用大量U程的程序中Q用线E组l织U程可能很有帮助。可以将它们看作是计机上的目录和文件结构?br />
U程间发?br />
当线E在l箋执行前需要等待一个条件时Q仅?synchronized 关键字是不够的。虽?synchronized 关键字阻止ƈ发更C个对象,但它没有实现U程间发信。Object cMؓ此提供了三个函数Qwait()、notify() ?notifyAll()。以全球气候预程序ؓ例。这些程序通过地球分多单元,在每个@环中Q每个单元的计算都是隔离q行的,直到q些D于稳定,然后盔R单元之间׃交换一些数据。所以,从本质上Ԍ在每个@环中各个U程都必ȝ待所有线E完成各自的d以后才能q入下一个@环。这个模型称为屏蔽同步,下例说明了这个模型:
屏蔽同步
public class BSync {
int totalThreads;
int currentThreads;
public BSync(int x) {
totalThreads = x;
currentThreads = 0;
}
public synchronized void waitForAll() {
currentThreads++;
if(currentThreads < totalThreads) {
try {
wait();
} catch (Exception e) {}
}
else {
currentThreads = 0;
notifyAll();
}
}
}
当对一个线E调?wait() Ӟ该线E就被有效阻塞,只到另一个线E对同一个对象调?notify() ?notifyAll() 为止。因此,在前一个示例中Q不同的U程在完成它们的工作以后调?waitForAll() 函数Q最后一个线E将触发 notifyAll() 函数Q该函数释放所有的U程。第三个函数 notify() 只通知一个正在等待的U程Q当Ҏơ只能由一个线E用的资源q行讉K限制Ӟq个函数很有用。但是,不可能预知哪个线E会获得q个通知Q因取决?Java 虚拟?(JVM) 调度法?br />
?CPU 让给另一个线E?br />
当线E放弃某个稀有的资源(如数据库q接或网l端?Ӟ它可能调?yield() 函数临时降低自己的优先Q以便某个其他线E能够运行?br />
守护U程
有两cȝE:用户U程和守护线E。用LE是那些完成有用工作的线E?守护U程是那些仅提供辅助功能的线E。Thread cL供了 setDaemon() 函数。Java E序运行到所有用LE终止,然后它将破坏所有的守护U程。在 Java 虚拟?(JVM) 中,即?main l束以后Q如果另一个用LE仍在运行,则程序仍然可以l运行?br />
避免不提倡用的Ҏ
不提倡用的Ҏ是ؓ支持向后兼容性而保留的那些ҎQ它们在以后的版本中可能出现Q也可能不出现。Java 多线E支持在版本 1.1 和版?1.2 中做了重大修订,stop()、suspend() ?resume() 函数已不提倡用。这些函数在 JVM 中可能引入微妙的错误。虽然函数名可能听v来很׃hQ但h制诱惑不要用它们?br />
调试U程化的E序
在线E化的程序中Q可能发生的某些常见而讨厌的情况是死锁、活锁、内存损坏和资源耗尽?br />
死锁
死锁可能是多U程E序最常见的问题。当一个线E需要一个资源而另一个线E持有该资源的锁Ӟ׃发生死锁。这U情况通常很难。但是,解决Ҏ却相当好Q在所有的U程中按相同的次序获取所有资源锁。例如,如果有四个资??A、B、C ?D ? q且一个线E可能要获取四个资源中Q何一个资源的锁,则请保在获取对 B 的锁之前首先获取?A 的锁Q依此类推。如?#8220;U程 1”希望获取?B ?C 的锁Q?#8220;U程 2”获取?A、C ?D 的锁Q则q一技术可能导致阻塞,但它永远不会在这四个锁上造成死锁?br />
z锁
当一个线E忙于接受新d以致它永q没有机会完成Q何Q务时Q就会发生活锁。这个线E最l将出~冲区ƈDE序崩溃。试想一个秘书需要录入一信Q但她一直在忙于接电话,所以这信永远不会被录入?br />
内存损坏
如果明智C?synchronized 关键字,则完全可以避免内存错误这U气Mh的问题?br />
资源耗尽
某些pȝ资源是有限的Q如文g描述W。多U程E序可能耗尽资源Q因为每个线E都可能希望有一个这L资源。如果线E数相当大,或者某个资源的侯选线E数q远过了可用的资源敎ͼ则最好用资源池。一个最好的CZ是数据库q接池。只要线E需要用一个数据库q接Q它׃池中取出一个,使用以后再将它返回池中。资源池也称?资源库?br />
调试大量的线E?br />
有时一个程序因为有大量的线E在q行而极难调试。在q种情况下,下面的这个类可能会派上用场:
public class Probe extends Thread {
public Probe() {}
public void run() {
while(true) {
Thread[] x = new Thread[100];
Thread.enumerate(x);
for(int i=0; i<100; i++) {
Thread t = x[i];
if(t == null)
break;
else
System.out.println(t.getName() + “\t” + t.getPriority()
+ “\t” + t.isAlive() + “\t” + t.isDaemon());
}
}
}
}
限制U程优先U和调度
Java U程模型涉及可以动态更改的U程优先U。本质上Q线E的优先U是?1 ?10 之间的一个数字,数字大表明d紧急。JVM 标准首先调用优先U较高的U程Q然后才调用优先U较低的U程。但是,该标准对h相同优先U的U程的处理是随机的。如何处理这些线E取决于基层的操作系l策略。在某些情况下,优先U相同的U程分时q行; 在另一些情况下Q线E将一直运行到l束。请CQJava 支持 10 个优先Q基层操作系l支持的优先U可能要得多,q样会造成一些乱。因此,只能优先作ؓ一U很_略的工具用。最后的控制可以通过明智C?yield() 函数来完成。通常情况下,请不要依靠线E优先来控制线E的状态?

]]>
վ֩ģ壺
|
|
֦|
Ҧ|
|
ӳ|
|
ʡ|
|
|
|
̨ǰ|
|
|
|
|
Ž|
|
|
|
|
ƽ|
|
ľ|
|
ʢ|
|
|
|
Դ|
|
|
|
|
Ļ|
|
|
|
ʯ|
|
|