1. 如何创建线程
1.1 方式一:继承Thread类
- 继承Thread类
- 重写run方法
- 调用线程对象的start方法来启动该线程
class MyThread extends Thread{
@Override
public void run(){
for (int i = 0;i < 5;i ++){
System.out.println("--子线程--:" + i);
}
}
}
public class Demo {
public static void main(String[] args) {
Thread thread = new MyThread(); // 创建子线程
thread.start(); // 启动子线程
for (int i = 0;i < 5;i ++){
System.out.println("主线程:" + i);
}
}
}
- 主线程和子线程交替打印
主线程:0
主线程:1
--子线程--:0
主线程:2
--子线程--:1
--子线程--:2
--子线程--:3
--子线程--:4
主线程:3
主线程:4
- 为什么不是调用run方法?
答:直接调用run方法不会创建新的线程。为了在新的线程中执行run方法中的代码,你必须调用Thread对象的start方法。这样,JVM会启动一个新的线程,并在这个线程中调用run方法。 - 如果直接调用run方法,那么不会新建线程,是一个普通方法,会先后执行
--子线程--:0
--子线程--:1
--子线程--:2
--子线程--:3
--子线程--:4
主线程:0
主线程:1
主线程:2
主线程:3
主线程:4
1.2 方式二:实现Runnable接口
- 实现Runnable
- 重写run方法
- 创建实现接口的类对象
- 实例化Thread,并传入实现接口对象
- 启动线程
class Mythread implements Runnable{
@Override
public void run(){
for (int i = 0;i < 5;i++){
System.out.println("--子线程--:" + i);
}
}
}
public class Demo01 {
public static void main(String[] args) {
Mythread mythread = new Mythread(); // 实例化对象
Thread thread = new Thread(mythread); // 传入对象
thread.start(); // 启动子线程
for (int i = 0;i < 5;i++){
System.out.println("主线程:" + i);
}
}
}
主线程:0
主线程:1
--子线程--:0
主线程:2
--子线程--:1
主线程:3
--子线程--:2
主线程:4
--子线程--:3
--子线程--:4
1.3 方式三:实现Callable接口
- 实现Callable接口
- 实例化Callable接口的类对象
- 实例化FutureTask并传入对象
- 实例化Thread,并传入FutureTask对象
- 启动线程
class Mythread1 implements Callable<Integer>{
@Override
public Integer call(){
Integer sum = 0;
for (int i = 0;i < 5;i++){
sum += i;
}
return sum;
}
}
public class Demo02 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Mythread1 mythread = new Mythread1();
FutureTask<Integer> futureTask = new FutureTask<Integer>(mythread);
Thread thread = new Thread(futureTask);
thread.start();
Thread.sleep(1); // 模拟做其他事情
Random r = new Random();
if(r.nextInt(100) > 50){
System.out.println("Get useCallable result = " + futureTask.get()); // 获取结果
}else {
System.out.println("Cancel...........................");
System.out.println(futureTask.cancel(true));// 取消正在执行的任务
}
}
}
2. 总结
在官方源码注释说只有继承Thread类和实现Runnable接口两种,这两种不会返回结果,如果需要返回结果,就需要实现Callable接口。