在java中要实现多线程,有两种手段,一种是继承Thread类,另外一种是实现Runable接口.(准确讲是三种,还有一种实现Callable接口,并与Future、线程池结合使用)
一、扩展java.lang.Thread类
package cn.demo;
public class Thread1 extends Thread {
private String name;
public Thread1(String name){
this.name=name;
}
public void run(){
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行 : " + i);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.demo;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread1 mth1=new Thread1("A");
Thread1 mth2=new Thread1("B");
mth1.start();
mth2.start();
}
}
输出结果:
A运行 : 0
B运行 : 0
B运行 : 1
B运行 : 2
A运行 : 1
B运行 : 3
A运行 : 2
B运行 : 4
A运行 : 3
A运行 : 4
程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用两个对象的start方法。另外两个线程也启动了。
多线程代码执行顺序是不确定的,每次执行的结果都是随机的。
二、实现java.lang.Runnable接口
- 定义类实现Runnable接口
- 覆盖Runnable接口中的run方法(将线程要运行的代码存放在该run方法中)
- 通过Thread类建立线程对象
- 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。(为什么要将Runnable接口的子类对象传递给Thread的构造函数。因为自定义的run方法所属的对象是runnable接口的子类对象。所以要让线程去指定指定对象的run方法,就必须明确该run方法所属对象)
- 调用Thread类的start方法开启你线程并调用Runnable接口子类的run方法
package cn.demo;
public class Thread2 implements Runnable {
private String name;
public Thread2(String name){
this.name=name;
}
@Override
public void run(){
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行 : " + i);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.demo;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(new Thread1("C")).start();
new Thread(new Thread1("D")).start();
}
}
输出结果:
C运行 : 0
D运行 : 0
C运行 : 1
D运行 : 1
C运行 : 2
D运行 : 2
C运行 : 3
D运行 : 3
C运行 : 4
D运行 : 4
实现方式和继承方式有什么区别?
实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。
区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable:线程代码存在接口的子类的run方法。