您的位置:首页 > 编程语言 > Java开发

Java多线程 之 Runnable Thread (一)

2016-06-01 09:43 309 查看
最近看的东西有些乱。励志从XOA2看起、学起,发现需要看下thrift,看着看着thrift,发现需要学学NIO,学完了NIO温习温习前面看的thrift,却要休假10天。休假回来,感觉要学学多线程。多线程这厮,看《Thinking in java》第21章的前几个小节,这是第3次了。这次要坚持下来,并且记录下来。——勉之!

程序做的事情可以抽象成一个一个“任务”,任务是由线程来驱动的,线程是一个进程中单一的顺序控制流。在java中用什么来定义任务呢?

1.Runnable

在java中可以通过实现Runnable接口来定义一个任务。如:

package org.fan.learn.thread.task;
/**
* Created by fan on 16-5-25.
*/
public class LiftOff implements Runnable {
private static int taskCunnt = 0;
private final int id = taskCunnt++;
private int countDown = 10;
private void status() {
System.out.print("Task(" + id + ")#" + (countDown > 0 ? countDown : "liftOff") + "   ");
}
public void run() {
while (countDown-- > 0) {
status();
Thread.yield();
}
}
}


package org.fan.learn.thread.simple;
import org.fan.learn.thread.task.LiftOff;
/**
* Created by fan on 16-5-31.
*/
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new LiftOff().run();
}

}
}


程序的执行结果如下所示:

Task(0)#9 Task(0)#8 Task(0)#7 Task(0)#6 Task(0)#5 Task(0)#4 Task(0)#3 Task(0)#2 Task(0)#1 Task(0)#liftOff Task(1)#9 Task(1)#8 Task(1)#7 Task(1)#6 Task(1)#5 Task(1)#4 Task(1)#3 Task(1)#2 Task(1)#1 Task(1)#liftOff Task(2)#9 Task(2)#8 Task(2)#7 Task(2)#6 Task(2)#5 Task(2)#4 Task(2)#3 Task(2)#2 Task(2)#1 Task(2)#liftOff Task(3)#9 Task(3)#8 Task(3)#7 Task(3)#6 Task(3)#5 Task(3)#4 Task(3)#3 Task(3)#2 Task(3)#1 Task(3)#liftOff Task(4)#9 Task(4)#8 Task(4)#7 Task(4)#6 Task(4)#5 Task(4)#4 Task(4)#3 Task(4)#2 Task(4)#1 Task(4)#liftOff

这里直接调用了Runnable接口的run方法。注意这个run方法是没有任何返回值的。因此无法直到任务执行的状态返回值。但是驱动任务时很少这么写,一般都是由线程来驱动任务。

Thread

package org.fan.learn.thread.simple;
import org.fan.learn.thread.task.LiftOff;
/**
* Created by fan on 16-5-31.
*/
public class Main2 {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new LiftOff()).start();
}
System.out.println("Waiting for liftOff!");
}
}


程序执行结果如下所示:

Task(0)#9 Task(1)#9 Task(0)#8 Task(1)#8 Task(0)#7 Task(1)#7 Task(0)#6 Task(1)#6 Task(0)#5 Task(1)#5 Task(0)#4 Task(1)#4 Task(0)#3 Task(1)#3 Task(0)#2 Task(1)#2 Task(0)#1 Task(1)#1 Task(0)#liftOff Task(1)#liftOff Task(2)#9 Task(2)#8 Waiting for liftOff!

Task(2)#7 Task(3)#9 Task(2)#6 Task(3)#8 Task(2)#5 Task(3)#7 Task(4)#9 Task(3)#6 Task(2)#4 Task(3)#5 Task(4)#8 Task(3)#4 Task(2)#3 Task(3)#3 Task(4)#7 Task(3)#2 Task(2)#2 Task(3)#1 Task(4)#6 Task(3)#liftOff Task(2)#1 Task(4)#5 Task(2)#liftOff Task(4)#4 Task(4)#3 Task(4)#2 Task(4)#1 Task(4)#liftOff

Process finished with exit code 0

注意

(1)上面调用的是Thread.start()。start方法会为线程的执行做一些准备工作,然后调用Runnable接口的run方法。

(2)可以看到main中先输出了“Waiting for liftOff”方法,后面还有线程在执行。说明在main中执行完输出退出程序时,new出的Thread对象依然还在内存中,没有被垃圾回收,依然可以继续执行,直到其run方法执行完。其实,每个Thread“注册”了自己,因此JVM中确实有一个对它的引用,所以在main退出后,没有被垃圾回收。Thread对象有别于普通对象。

run与start的区别

run方法不会启动新的线程,在调用run方法的线程中运行。

而start方法会new出一个新线程,在这个新线程中执行。

这也就是为什么需要区分“线程”和“任务”这两个概念。线程是为了驱动任务的。可以这么说,任务是一个静态的概念,而线程是一个动态的概念。

下面有个例子(该例子来自网络):

// Demo.java 的源码
class MyThread extends Thread{
public MyThread(String name) {
super(name);
}

public void run(){
System.out.println(Thread.currentThread().getName()+" is running");
}
};

public class Demo {
public static void main(String[] args) {
Thread mythread=new MyThread("mythread");

System.out.println(Thread.currentThread().getName()+" call mythread.run()");
mythread.run();

System.out.println(Thread.currentThread().getName()+" call mythread.start()");
mythread.start();
}
}


运行结果:

main call mythread.run()
main is running
main call mythread.start()
mythread is running


(01) Thread.currentThread().getName()是用于获取“当前线程”的名字。当前线程是指正在cpu中调度执行的线程。

(02) mythread.run()是在“主线程main”中调用的,该run()方法直接运行在“主线程main”上。

(03) mythread.start()会启动“线程mythread”,“线程mythread”启动之后,会调用run()方法;此时的run()方法是运行在“线程mythread”上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息