创建线程的常用三种方式:
-
继承Thread类
-
实现Runnable接口
-
实现Callable接口(JDK1.5>=)
-
线程池方式创建
通过继承Thread类或者实现Runnable接口、Callable接口都可以实现多线程,不过实现Runnable 接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法返回值,可以声明抛出异 常而已。因此将实现Runnable接口和实现Callable接口归为一种方式。这种方式与继承Thread方式 之间的主要差别如下。
继承Thread类
实现的步骤:
-
创建Thread类的子类
-
重写run方法
-
创建线程对象
-
启动线程
package thread;
public class ThreadDemo {
public static void main(String[] args) {
/**
* 线程的第一种实现方式
* 通过创建Thread类的子类来实现
*/
System.out.println("main方法开启了");
// Java中的线程 本质上就是一个Thread对象
MyThread thread = new MyThread();
// 启动一个新的线程
thread.start();
for(int i = 0 ; i< 100 ; i++){
System.out.println("main方法的循环..."+i);
}
System.out.println("main方法结束了");
}
}
package thread;
public class MyThread extends Thread{
/**
* 第一个自定义的线程类
* 继承Thread父类
* 重写run方法
*/
@Override
public void run() {
System.out.println("子线程执行了");
}
}
注意点:
-
启动线程是使用start方法而不是run方法
-
线程不能启动多次,如果要创建多个线程,那么就需要创建多个Thread对象
实现Runnable接口
实现的步骤:
-
创建Runable的实现类
-
重写run方法
-
创建Runable实例对象(通过实现类来实现)
-
创建Thread对象,并把第三部的Runable实现作为Thread构造方法的参数
-
启动线程
package thread;
public class ThreadDemo {
public static void main(String[] args) {
/**
* 线程的第二种方式
* 本质是创建Thread对象的时候传递了一个Runable接口实现
* @param args
*/
System.out.println("main方法开启了");
// 创建一个新的线程 Thread对象
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
for(int i = 0 ; i< 100 ; i++){
System.out.println("main方法的循环..."+i);
}
System.out.println("main方法结束了");
}
}
package thread;
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("子线程执行了");
}
}
实现Runable接口的好处:
-
可以避免Java单继承带来的局限性
-
适合多个相同的程序代码处理同一个资源的情况,把线程同程序的代码和数据有效的分离,较好的体现了面向对象的设计思想
Callable的方式
前面我们介绍的两种创建线程的方式都是重写run方法,而且run方法是没有返回结果的,也就是main方法是不知道开启的线程什么时候开始执行,什么时候结束执行,也获取不到对应的返回结果。而且run方法也不能把可能产生的异常抛出。在JDK1.5之后推出了通过实现Callable接口的方式来创建新的线程,这种方式可以获取对应的返回结果
package thread;
import java.util.concurrent.FutureTask;
public class ThreadDemo {
/**
* 创建线程的第三种实现方式:
* Callable方式
*/
public static void main(String[] args) throws Exception {
// 创建一个Callable实例
MyCallable callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 获取一个线程 肯定是要先创建一个Thread对象 futureTask本质上是Runable接口的实现
Thread thread = new Thread(futureTask);
System.out.println("main方法start");
// 本质还是执行的 Runable中的run方法,只是 run方法调用了call方法罢了
thread.start();
// 获取开启的线程执行完成后返回的结果
System.out.println(futureTask.get());
System.out.println("main方法end");
}
}
package thread;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
/**
* 创建Callable的实现类
* 我们需要指定Callable的泛型,这个泛型是返回结果的类型
*/
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i = 1 ; i <= 100 ; i ++){
sum += i;
}
return sum;
}
}