前言
我们都知道通过继承Thread和实现Runnable接口都能创建线程,那么他们有什么区别呢?
继承Thread创建线程
通过extends
关键字继承Thread然后覆盖其run
方法就可以实现一个自己的线程。启动的时候只需要调用thread的start
方法就可以了。
public class ExtendThreadDemo extends Thread {
//定一个线程的名称
private String name;
//带参数的构造方法
ExtendThreadDemo(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("[ExtendThreadDemo]我是线程:ExtendThreadDemo-" + name);
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
ExtendThreadDemo threadDemo = new ExtendThreadDemo(String.valueOf(i));
threadDemo.start();
}
}
}
打印日志:
[ExtendThreadDemo]我是线程:ExtendThreadDemo-0
[ExtendThreadDemo]我是线程:ExtendThreadDemo-1
[ExtendThreadDemo]我是线程:ExtendThreadDemo-2
[ExtendThreadDemo]我是线程:ExtendThreadDemo-4
[ExtendThreadDemo]我是线程:ExtendThreadDemo-3
从日志中我们可以看出,一共创建了5个线程这5个线程是异步执行
的。
实现Runnable接口创建线程
通过implements
关键字实现Runnable
接口并且实现里面的run方法来创建线程。注意这里启动线程的时候需要使用new Thread(Runable).start()
方法。
public class RunnableThreadDemo implements Runnable {
//定一个线程的名称
private String name;
//带参数的构造方法
RunnableThreadDemo(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("[RunnableThreadDemo]我是线程:RunnableThreadDemo" + name);
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
RunnableThreadDemo threadDemo = new RunnableThreadDemo(String.valueOf(i));
new Thread(threadDemo).start();
}
}
}
打印日志:
[RunnableThreadDemo]我是线程:RunnableThreadDemo3
[RunnableThreadDemo]我是线程:RunnableThreadDemo4
[RunnableThreadDemo]我是线程:RunnableThreadDemo2
[RunnableThreadDemo]我是线程:RunnableThreadDemo1
[RunnableThreadDemo]我是线程:RunnableThreadDemo0
我们可以看出通过实现Runable接口
的方式同样可以达到异步执行
线程的目的。
线程run方法和start方法区别
线程启动使用的是start()方法
,其实start方法里也是调用了run()方法,他们之间的区别是什么?
我们做一个测试,将上面的ExtendThreadDemo
类里面的main
方法稍作修改为:
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
ExtendThreadDemo threadDemo = new ExtendThreadDemo(String.valueOf(i));
threadDemo.run();
}
}
也就是将里面的start()方法换成了run()方法。打印结果:
[ExtendThreadDemo]我是线程:ExtendThreadDemo-0
[ExtendThreadDemo]我是线程:ExtendThreadDemo-1
[ExtendThreadDemo]我是线程:ExtendThreadDemo-2
[ExtendThreadDemo]我是线程:ExtendThreadDemo-3
[ExtendThreadDemo]我是线程:ExtendThreadDemo-4
这里线程打印结果的顺序是我们同步启动线程的顺序(无论试多少次都是这个结果),这说明线程没有异步启动,而是同步执行了里面的run()方法而已。
start方法源码分析
public synchronized void start() {
//(1)判断状态是否是0。0代表是新建状态NEW,否则抛出异常
if (threadStatus != 0)
throw new IllegalThreadStateException();
//(2)将线程添加到线程组列表中
group.add(this);
//(3)将是否进入就绪态设置为false
boolean started = false;
try {
//(4)调用private native void start0();方法,推测方法就是请求CPU分配时间片方法
start0();
//(5)调用native方法成功,将状态修改为true
started = true;
} finally {
try {
//(6)调用native方法失败,将回退操作
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
第(4)这里调用了Java的native方法为:
private native void start0();
所谓的navtiv方法简单地讲,一个Native Method
就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。
引用:Java的native方法
https://blog.csdn.net/wike163/article/details/6635321
Thread和Runable创建线程的区别
简单写一个测试类CreateThreadTest里面的线程都使用内部类实现:
public class CreateThreadTest {
//内部类继承Thread创建线程
private class ExtendThreadDemo extends Thread {
//定一个循环数字
private int a = 3;
@Override
public void run() {
//线程名称
String name = Thread.currentThread().getName();
System.out.println(name + " 创建成功");
while (a > 0) {
a--;
System.out.println("[ExtendThreadDemo]" + name + "我是数字:" + a);
}
}
}
//内部类继承实现Runnable创建线程
private class RunnableThreadDemo implements Runnable {
//定一个循环数字
private int a = 3;
@Override
public void run() {
//线程名称
String name = Thread.currentThread().getName();
System.out.println(name + " 创建成功");
while (a > 0) {
a--;
System.out.println("[ExtendThreadDemo]" + name + "我是数字:" + a);
}
}
}
//使用extend创建线程测试
public void extendThreadTest() {
ExtendThreadDemo extendThreadDemo1 = new ExtendThreadDemo();
ExtendThreadDemo extendThreadDemo2 = new ExtendThreadDemo();
ExtendThreadDemo extendThreadDemo3 = new ExtendThreadDemo();
extendThreadDemo1.start();
extendThreadDemo2.start();
extendThreadDemo3.start();
}
//使用implements创建线程测试
public void runnableThreadTest() {
RunnableThreadDemo runnableThreadDemo = new RunnableThreadDemo();
Thread runnableThreadDemo1 = new Thread(runnableThreadDemo);
Thread runnableThreadDemo2 = new Thread(runnableThreadDemo);
Thread runnableThreadDemo3 = new Thread(runnableThreadDemo);
runnableThreadDemo1.start();
runnableThreadDemo2.start();
runnableThreadDemo3.start();
}
//main方法测试
public static void main(String[] args) {
CreateThreadTest mainTest = new CreateThreadTest();
mainTest.extendThreadTest();
// mainTest.runnableThreadTest();
}
}
当使用extendThreadTest进行测试的时候,打印日志如下:
Thread-0 创建成功
[ExtendThreadDemo]Thread-0我是数字:2
[ExtendThreadDemo]Thread-0我是数字:1
[ExtendThreadDemo]Thread-0我是数字:0
Thread-1 创建成功
[ExtendThreadDemo]Thread-1我是数字:2
[ExtendThreadDemo]Thread-1我是数字:1
[ExtendThreadDemo]Thread-1我是数字:0
Thread-2 创建成功
[ExtendThreadDemo]Thread-2我是数字:2
[ExtendThreadDemo]Thread-2我是数字:1
[ExtendThreadDemo]Thread-2我是数字:0
当使用runnableThreadTest进行测试的时候,打印日志如下:
Thread-0 创建成功
[ExtendThreadDemo]Thread-0我是数字:2
[ExtendThreadDemo]Thread-0我是数字:1
[ExtendThreadDemo]Thread-0我是数字:0
Thread-1 创建成功
Thread-2 创建成功
从以上结果我们可以看出,如果继承Thread的话里面的变量在每一个线程中都会各自复一份
,但是如果使用Runable多个线程之间可以共享数据变量
。
关于线程的生命周期可以参考:JAVA线程的生命周期以及5种状态转换
https://blog.csdn.net/u011047968/article/details/106857781
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72685.html