结果如下:
Thread[Thread-0,10,main]: 4
Thread[Thread-2,1,main]: 4
Thread[Thread-1,1,main]: 4
Thread[Thread-3,1,main]: 5
Thread[Thread-3,1,main]: 4
Thread[Thread-4,1,main]: 5
Thread[Thread-4,1,main]: 4
Thread[Thread-3,1,main]: 3
Thread[Thread-0,10,main]: 2
Thread[Thread-3,1,main]: 2
Thread[Thread-4,1,main]: 2
Thread[Thread-1,1,main]: 2
Thread[Thread-5,1,main]: 3
Thread[Thread-0,10,main]: 1
Thread[Thread-1,1,main]: 1
大家可以到线程1的优先级最高,先被打印出来,其余线程都是随机进行的。虽然java虚拟机里面线程有10个优先级别,但是现实中在不同的操作系统里都是映射的不是特别好,因此使用者三个静态变量是最保险的做法。
下面我要讲到另外一种实现java里线程的方式接口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接口从而解决了上面的问题,让我们定义的类既能继承父类的业务信息,又能具有线程的特点。大家看下面的代码:
结果如下:
#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类,然后把它设为业务类的一个属性,这种做法想想就觉得是多此一。