创建线程的三个方法
1.继承thread类创建线程类
- 第一步:定义thread类的子类,并重写该类的run方法,run方法的方法体就代表了线程需要完成的任务
- 第二步:创建thread类的子类的实例,即创建了线程对象
- 第三步:调用线程对象的start方法来启动该线程
以下为第一种创建方式的代码示例及其部分运行结果
//定义继承Thread类的子类
public class TThread extends Thread {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "" + i);
if (i == 20) {
//实例化线程对象,并调用线程对象的start方法
new TThread().start();
new TThread().start();
}
}
}
int i = 0;
//重写父类的run方法,里面是线程的需要完成的任务代码
public void run() {
for (; i < 100; i++) {
System.out.println(getName() + "" + i);
}
}
}
main10//主线程运行
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
Thread-00//创建了名为Thread-0的子线程
Thread-01
Thread-02
Thread-03
Thread-04
Thread-10//创建了名为Thread-1的子线程,所以共创建了2个线程执行run方法
Thread-11
Thread-12
2.通过runable接口创建线程类
- 定义runable接口的实现类,并重写该类的run方法,该run方法的方法体同样是该线程的执行体
- 创建该实现类的实例,并将该实例作为thread的参数来创建Thread对象。该对象才是真正的线程对象
- 调用线程对象的start方法来启动线程。
以下为第二种创建方式的代码示例及其部分运行结果
//创建了Runable接口的实例RThread
public class RThread implements Runnable {
public static void main(String[] args) {
for(int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+""+i);
if (i == 20){
//实例化RThread类
RThread rt = new RThread();
//实例化Thread类并把Runable接口的实例对象传入,共创建了两个线程对象。
new Thread(rt,"新线程1").start();
new Thread(rt,"新线程2").start();
}
}
}
private int i;
//重写了run方法
public void run(){
for(int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+""+i);
}
}
}
main12//主线程运行
main13
main14
main15
main16
main17
main18
main19
main20
新线程10//创建子线程1
main21
新线程20
新线程11
新线程21//创建子线程2
3.通过callable接口创建线程类
- 定义callable接口的实现类,并实现call方法,该call方法将作为线程执行体,并且有返回值
- 创建callable的实例,使用FutureTask类来包装callable对象,该类对象封装了该callable对象的方法的返回值
- 使用FutureTask对象作为thread对象的target创建并启动新线程
- 调用FutureTask对象的get方法来获得子线程结束后的返回值。
以下为第三种创建方式的代码示例及其部分运行结果
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
//创建了Callable接口的实例CThread
public class CThread implements Callable<Integer> {
public static void main(String[] args) throws Exception{
//实例化实现了Runable接口的CThread类
CThread ctt = new CThread();t
//使用FutureTask类包装实例化对象ctt,该对象封装了call方法的返回值,通过get()可以随时取出子线程执行结果
FutureTask<Integer> ft = new FutureTask<>(ctt);
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量i的值"+i);
if(i == 20){
new Thread(ft,"有返回值的线程").start();
}
}
try {
System.out.println("子线程的返回值"+ft.get());
}catch (InterruptedException e){
e.printStackTrace();
}
}
//重写call方法
@Override
public Integer call() throws Exception {
int i=0;
for(;i<100;){
i++;
System.out.println(Thread.currentThread().getName()+""+i);
}
return i;
}
}
main的循环变量i的值19
main的循环变量i的值20
main的循环变量i的值21
main的循环变量i的值22
main的循环变量i的值23
main的循环变量i的值24
main的循环变量i的值25
有返回值的线程1
main的循环变量i的值26
有返回值的线程2
-
-
-
有返回值的线程99
有返回值的线程100
子线程的返回值100//执行完主线程的的for循环,执行最后的try语句。
4.创建方法的比较
1、继承Thread类(不推荐):只能被单继承,不推荐使用
2、实现Runable的接口(推荐):不需要返回值时,推荐使用
3、实现Callable接口(JDK1.5): 核心方法叫call()方法(相当于run()),有返回值,推荐使用