技术开发 频道

JAVA线程:两种不同创建方式全面解析

  结果如下:

Thread[Thread-0,10,main]: 5
Thread[Thread-1,1,main]: 5
Thread[Thread
-0,10,main]: 4
Thread[Thread-2,1,main]: 5
Thread[Thread
-2,1,main]: 4
Thread[Thread-2,1,main]: 3
Thread[Thread
-1,1,main]: 4
Thread[Thread-2,1,main]: 2
Thread[Thread
-3,1,main]: 5
Thread[Thread-0,10,main]: 3
Thread[Thread
-3,1,main]: 4
Thread[Thread-2,1,main]: 1
Thread[Thread
-4,1,main]: 5
Thread[Thread-1,1,main]: 3
Thread[Thread
-4,1,main]: 4
Thread[Thread
-3,1,main]: 3
Thread[Thread-5,1,main]: 5
Thread[Thread
-0,10,main]: 2
Thread[Thread-5,1,main]: 4
Thread[Thread
-3,1,main]: 2
Thread[Thread-4,1,main]: 3
Thread[Thread
-4,1,main]: 2
Thread[Thread-4,1,main]: 1
Thread[Thread
-1,1,main]: 2
Thread[Thread-3,1,main]: 1
Thread[Thread
-5,1,main]: 3
Thread[Thread
-0,10,main]: 1
Thread[Thread-5,1,main]: 2
Thread[Thread
-1,1,main]: 1
Thread[Thread-5,1,main]: 1

   大家可以到线程1的优先级最高,先被打印出来,其余线程都是随机进行的。虽然java虚拟机里面线程有10个优先级别,但是现实中在不同的操作系统里都是映射的不是特别好,因此使用者三个静态变量是最保险的做法。

  下面我要讲到另外一种实现java里线程的方式接口Runnable

package cn.com.sxia;public class RunnableThread implements Runnable
{
        
private int countDown = 5;
        
public String toString(){
        
return "#" + Thread.currentThread().getName() + ": " + countDown;
    }
    @Override
    
public void run() {
        
while(true){
            System.out.println(
this);
            
if (--countDown == 0)
                
return;
        }
    }
        
public static void main(String[] args) {
        
for (int i = 1;i <= 5;i++)
        {
            
new Thread(new RunnableThread(),"" + i).start();
        }
    }
}

   为什么java会提供另外一种线程实现的方式呢?我们知道java里没有多继承,一个类继承了某一个父类后就不能再继承别的类了,这就产生了一个问题,在实际的开发中,子类所要继承的父类往往都是包含业务信息的,而Thread类仅仅是为了实现线程功能而定义的,没有必要让定义好的类直接继承Thread类,为了解决java多继承给线程实现带来的问题,java里使用了一个变通的方案,实现了一个Runnable接口从而解决了上面的问题,让我们定义的类既能继承父类的业务信息,又能具有线程的特点。大家看下面的代码:

  结果如下:

#1: 5
#
2: 5
#
1: 4
#
2: 4
#
3: 5
#
1: 3
#
4: 5
#
3: 4
#
2: 3
#
2: 2
#
3: 3
#
4: 4
#
4: 3
#
1: 2
#
4: 2
#
3: 2
#
2: 1
#
5: 5
#
3: 1
#
4: 1
#
1: 1
#
5: 4
#
5: 3#5: 2#5: 1

  Runnable接口只有一个run方法,只要实现这个run方法就可以了,构造线程对象,只要把实现Runnable接口的类创建的对象作为Thread类的构造参数传入就行了。

  虽然实现Runnable接口创建线程同样可以产生线程实例,不过使用Runnable接口定义的线程还是有些特别的地方,我总结了下,有以下两种:

  ①每个线程都有一个名字,前面通过继承Thread来创建线程类里有一个getName方法来获得线程的名称,但是用Runnable接口,必须通过调用Thread.currentThread().getName()方法来获取线程的名称。Thread.currentThread()获取当前运行线程的引用。

  ②由于Runnable只是一个接口,里面不包含任何和线程相关的信息,所以用Runnable构建的Thread对象使用时候要调用start方法才能让线程调用run方法

  通过对Runnable接口实现线程让我有了一个新的想法:我们使用线程往往是需要线程提供的功能,我们不一定因为需要线程而去改变整个程序的组织结构,所以直接继承Thread类往往不可取,但是Runnable是不是唯一的解决方案了?想让类授予线程的功能是不是还可以有别的实现方式了?这种想法让我想到了两种替代方案,一个是单独构造一个继承了Thread类,然后把它设为业务类的一个属性,这种做法想想就觉得是多此一。

 

0
相关文章