分享
 
 
 

介绍JAVA线程、线程类及Runnable(2)

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

用Java线程获取优异性能(I)——介绍线程、线程类及Runnable

Jeff Friesen 著 刘建华 编译

怎样使用名称

在一个调试会话期间,使用用户友好方式从另一个线程区别其中一个线程证明是有帮助的。要区分其中一个线程,Java给一个线程取一个名称。Thread缺省的名称是一个短线连字符和一个零开始的数字符号。你可以接受Java的缺省线程名称或选择使用你自己的。为了能够自定义名称,Thread提供带有name参数和一个setName(String name)方法的构造器。Thread也提供一个getName()方法返回当前名称。表2显示了怎样通过Thread(String name)创建一个自定义名称和通过在run()方法中调用getName()检索当前名称:

表2.NameThatThread.java

// NameThatThread.java

class NameThatThread

{

public static void main (String [] args)

{

MyThread mt;

if (args.length == 0)

mt = new MyThread ();

else

mt = new MyThread (args [0]);

mt.start ();

}

}

class MyThread extends Thread

{

MyThread ()

{

//编译器创建等价于super()的字节代码

}

MyThread (String name)

{

super (name); //将名称传递给Thread超类

}

public void run ()

{

System.out.println ("My name is: " + getName ());

}

}

你能够在命令行向MyThread传递一个可选的name参数。例如,java NameThatThread X 建立X作为线程的名称。如果你指定一个名称失败,你将看到下面的输出:

My name is: Thread-1

如果你喜欢,你能够在MyThread(String name)构造器中将super(name)调用改变成setName(String name)调用——作为setName(name)后一种方法调用达到同样建立线程名称的目的——作为super(name)我作为练习保留给你们。

注意

Java主要将名称指派给运行main() 方法的线程,开始线程。你特别要看看当开始线程掷出一个例外对象时在线程“main”的例外显示的JVM的缺省例外处理打印消息。

休眠或停止休眠

在这一栏后面,我将向你介绍动画——在一个表面上重复画图形,这稍微不同于完成一个运动画面。要完成动画,一个线程必须在它显示两个连续画面时中止。调用Thread的静态sleep(long millis)方法强迫一个线程中止millis毫秒。另一个线程可能中断正在休眠的线程。如果这种事发生,正在休眠的线程将醒来并从sleep(long millis)方法掷出一个InterruptedException对象。结果,调用sleep(long millis)的代码必须在一个try代码块中出现——或代码方法必须在自己的throws子句中包括InterruptedException。

为了示范sleep(long millis),我写了一个CalcPI1应用程序。这个应用程序开始了一个新线程便于用一个数学运算法则计算数学常量pi的值。当新线程计算时,开始线程通过调用sleep(long millis)中止10毫秒。在开始线程醒后,它将打印pi的值,其中新线程存贮在变量pi中。表3给出了CalcPI1的源代码:

表3. CalcPI1.java

// CalcPI1.java

class CalcPI1

{

public static void main (String [] args)

{

MyThread mt = new MyThread ();

mt.start ();

try

{

Thread.sleep (10); //休眠10毫秒

}

catch (InterruptedException e)

{

}

System.out.println ("pi = " + mt.pi);

}

}

class MyThread extends Thread

{

boolean negative = true;

double pi; //缺省初始化为0.0

public void run ()

{

for (int i = 3; i < 100000; i += 2)

{

if (negative)

pi -= (1.0 / i);

else

pi += (1.0 / i);

negative = !negative;

}

pi += 1.0;

pi *= 4.0;

System.out.println ("Finished calculating PI");

}

}

如果你运行这个程序,你将看到输出如下(但也可能不一样):

pi = -0.2146197014017295

完成计算PI

为什么输出不正确呢?毕竟,pi的值应近似等于3.14159。回答是:开始线程醒得太快了。在新线程刚开始计算pi时,开始线程就醒过来读取pi的当前值并打印其值。我们可以通过将10毫秒延迟增加为更长的值来进行补偿。这一更长的值(不幸的是它是依赖于平台的)将给新线程一个机会在开始线程醒过来之前完成计算。(后面,你将学到一种不依赖平台的技术,它将防止开始线程醒来直到新线程完成。)

注意

线程同时提供一个sleep(long millis, int nanos)方法,它将线程休眠millis 毫秒和nanos 纳秒。因为多数基于JVM的平台都不支持纳秒级的分解度,JVM 线程处理代码将纳秒数字四舍五入成毫秒数字的近似值。如果一个平台不支持毫秒级的分解度,JVM 线程处理代码将毫秒数字四舍五入成平台支持的最小级分解度的近似倍数。

它是死的还是活的?

当一个程序调用Thread的start()方法时,在一个新线程调用run()之前有一个时间段(为了初始化)。run()返回后,在JVM清除线程之前有一段时间通过。JVM认为线程立即激活优先于线程调用run(),在线程执行run()期间和run()返回后。在这时间间隔期间,Thread的isAlive()方法返回一个布尔真值。否则,方法返回一个假值。

isAlive()在一个线程需要在第一个线程能够检查其它线程的结果之前等待另一个线程完成其run()方法的情形下证明是有帮助的。实质上,那些需要等待的线程输入一个while循环。当isAlive()为其它线程返回真值时,等待线程调用sleep(long millis) (或 sleep(long millis, int nanos))周期性地休眠 (避免浪费更多的CPU循环)。一旦isAlive()返回假值,等待线程便检查其它线程的结果。

你将在哪里使用这样的技术呢?对于起动器,一个CalcPI1的修改版本怎么样,在打印pi的值前开始线程在哪里等待新线程的完成?表4的CalcPI2源代码示范了这一技术:

表4. CalcPI2.java

// CalcPI2.java

class CalcPI2

{

public static void main (String [] args)

{

MyThread mt = new MyThread ();

mt.start ();

while (mt.isAlive ())

try

{

Thread.sleep (10); //休眠10毫秒

}

catch (InterruptedException e)

{

}

System.out.println ("pi = " + mt.pi);

}

}

class MyThread extends Thread

{

boolean negative = true;

double pi; //缺省初始化成0.0

public void run ()

{

for (int i = 3; i < 100000; i += 2)

{

if (negative)

pi -= (1.0 / i);

else

pi += (1.0 / i);

negative = !negative;

}

pi += 1.0;

pi *= 4.0;

System.out.println ("Finished calculating PI");

}

}

CalcPI2的开始线程在10毫秒时间间隔休眠,直到mt.isAlive ()返回假值。当那些发生时,开始线程从它的while循环中退出并打印pi的内容。如果你运行这个程序,你将看到如下的输出(但不一定一样):

完成计算PI

pi = 3.1415726535897894

这不,现在看上去更精确了?

注意

一个线程可能对它自己调用isAlive() 方法。然而,这毫无意义,因为isAlive()将一直返回真值。

合力

因为while循环/isAlive()方法/sleep()方法技术证明是有用的,Sun将其打包进三个方法组成的一个组合里:join(),join(long millis)和join(long millis, int nanos)。当当前线程想等待其它线程结束时,经由另一个线程的线程对象引用调用join()。相反,当它想其中任意线程等待其它线程结束或等待直到millis毫秒和nanos纳秒组合通过时,当前线程调用join(long millis)或join(long millis, int nanos)。(作为sleep()方法,JVM 线程处理代码将对join(long millis)和join(long millis,int nanos)方法的参数值四舍五入。)表5的CalcPI3源代码示范了一个对join()的调用:

表5. CalcPI3.java

// CalcPI3.java

class CalcPI3

{

public static void main (String [] args)

{

MyThread mt = new MyThread ();

mt.start ();

try

{

mt.join ();

}

catch (InterruptedException e)

{

}

System.out.println ("pi = " + mt.pi);

}

}

class MyThread extends Thread

{

boolean negative = true;

double pi; //缺省初始化成0.0

public void run ()

{

for (int i = 3; i < 100000; i += 2)

{

if (negative)

pi -= (1.0 / i);

else

pi += (1.0 / i);

negative = !negative;

}

pi += 1.0;

pi *= 4.0;

System.out.println ("Finished calculating PI");

}

}

CalcPI3的开始线程等待与MyThread对象有关被mt引用的线程结束。接着开始线程打印pi的值,其值与CalcPI2的输出一样。

警告

不要试图将当前线程与其自身连接,因为这样当前线程将要永远等待。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有