学习线程也是一种摆脱传统编程思维的奇妙之旅,这也是我想好好复习线程的重要原因之一,对线程的学习完全可以当做一门新语言来进行,而且各种不同语言实现线程的差异度都不大,这也是跳出语言框框的一次重要实践。
让我们回归到程序里吧,上面的例子里我们不断执行程序会发现:每次运行的结果都不一样,名称不同的线程会交替运行,这到底是什么原因造成的呢?产生的原因是java虚拟机里线程的调度机制,到底哪个线程先执行那个线程后执行,线程调度是使用一个非常随机的方式进行管理的,导致结果输出的混乱。解决这个问题的方法就是使用Thread所带的join()方法,大家请看下面的代码:
package cn.com.sxia;public class SimpleThread extends Thread {
private int countDown = 5;//构建的Thread对象内部使用的数据
private static int threadCount = 0;//静态变量属于类,目的是为了每个构建的线程定义一个名称
public SimpleThread(){
super("" + ++threadCount);
start();
}
public String toString(){
return "#" + getName() + ": " + countDown;
}
public void run(){
while(true){
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0;i < 5;i++)
{
new SimpleThread().join();
}
}
}
private int countDown = 5;//构建的Thread对象内部使用的数据
private static int threadCount = 0;//静态变量属于类,目的是为了每个构建的线程定义一个名称
public SimpleThread(){
super("" + ++threadCount);
start();
}
public String toString(){
return "#" + getName() + ": " + countDown;
}
public void run(){
while(true){
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0;i < 5;i++)
{
new SimpleThread().join();
}
}
}
结果如下:
#1: 5
#1: 4
#1: 3
#1: 2
#1: 1
#2: 5
#2: 4
#2: 3
#2: 2
#2: 1
#3: 5
#3: 4
#3: 3
#3: 2
#3: 1
#4: 5
#4: 4
#4: 3
#4: 2
#4: 1
#5: 5
#5: 4
#5: 3
#5: 2
#5: 1
#1: 4
#1: 3
#1: 2
#1: 1
#2: 5
#2: 4
#2: 3
#2: 2
#2: 1
#3: 5
#3: 4
#3: 3
#3: 2
#3: 1
#4: 5
#4: 4
#4: 3
#4: 2
#4: 1
#5: 5
#5: 4
#5: 3
#5: 2
#5: 1
大家看到了输出的结果是按线程构建的顺序进行的,这个现象说明了join()方法可以改变java里线程随机调度的现象,join方法会让使用join方法的线程处于等待的状态,只有当正在执行线程结束运行后后才会调用使用到join方法的线程。
前面讲到了,线程对象要被销毁要满足两个条件:一个是该线程对象没有被引用,一个是run方法停止运行了。但是当线程跳出了run方法,java虚拟机不一定知道线程已经执行完毕,这个需要一个过程,因此java中有了个yield方法,这个方法告诉java虚拟机,线程的任务已经完成了,可以释放该线程的CPU留给其他线程使用了,下面是使用yield方法的例子:
package cn.com.sxia;public class YieldingThread extends Thread{
private int countDown = 5;
private static int threadCount = 0;
public YieldingThread()
{
super("" + ++threadCount);
start();
}
public String toString(){ return "#" + getName() + ": " + countDown;
}
public void run()
{
while(true)
{
System.out.println(this);
if (--countDown == 0)
return;
yield();
}
}
public static void main(String[] args)
{
for (int i = 0;i < 5;i++)
{
new YieldingThread();
}
}
}
private int countDown = 5;
private static int threadCount = 0;
public YieldingThread()
{
super("" + ++threadCount);
start();
}
public String toString(){ return "#" + getName() + ": " + countDown;
}
public void run()
{
while(true)
{
System.out.println(this);
if (--countDown == 0)
return;
yield();
}
}
public static void main(String[] args)
{
for (int i = 0;i < 5;i++)
{
new YieldingThread();
}
}
}