最近在做的项目中有个模块正好用到了线程技术,在做的时候感觉到线程这块的基础还不够扎实,借机又复写了一遍线程的基础知识,今天要跟大家分享的是创建线程的两种传统方式。
我们知道在java中线程是用Thread对象来表示的,线程的执行由Thread类的start()来启动,并调用Thread类中的run(),而Thread类源码中的run()非常简单:
public void run() {
if (target != null) {
target.run();
}
}
往往在具体的项目中,我们要定义符合具体需求的方法体,所以第一种创建方式就不言而喻了--创建Thread类的子类对象,复写父类的run():
Thread thread = new Thread(){
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName());
}
}
};
//执行线程--调用Thread子类对象里的run()
thread.start();
这是创建线程的第一种方式,创建现成的第二种方式要从Thread这个类的源码入手,我们知道Thread对象是线程,线程要执行的代码是封装在run()内的,在Thread类的run()方法体,有一个if分支判断,判断target参数,这个target参数是Runnable类型。
Thread类中有一个构造方法:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
这个构造方法将Runnable对象作为参数传入了init方法,在init方法中又给target参数进行了赋值:
this.target = target;
因此,创建线程的第二种方式就是--利用Thread类上述的构造方法创建线程
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* Runnable对象是线程要运行的代码宿主(线程要运行的代码是放在Runnable对象里的)
*/
System.out.println(Thread.currentThread().getName());
}
}
});
thread2.start();
此处new Thread()是创建了一个线程,在这个构造函数里又创建了Runnable接口的子类对象,因为Runnable接口本身有run(),所以在接口的实现里要复写这个run(),线程要执行的代码也写在这个run()里。
以上的这两种方法就是创建线程的两种传统方式。第一种方式与第二种方式的区别(除去理论上的那几点区别外,谈谈个人对这两种创建方式独有的理解)在于,第二种创建线程的方式更能体现java面向对象编程的特性,new Thread()是创建线程对象,线程对象要执行的方法又作了一次封装,单独放在了Runnable类型的对象里。