Javaz 创建线程主要有三种方式:继承 Thread 类创建线程、实现 Runnable 接口创建线程和实现 Callable 和 Future 创建线程。
# 继承 Thread 类
public class Thread1 extends Thread { | |
@Override | |
public void run() { | |
for (int i = 0; i < 10; i++) { | |
System.out.println(getName() + ": " + i); | |
} | |
} | |
public static void main(String[] args) { | |
for (int i = 0; i < 10; i++) { | |
System.out.println(Thread.currentThread().getName() + ": " + i); | |
if (i == 2) { | |
new Thread1().start(); | |
new Thread1().start(); | |
} | |
} | |
} | |
} |
# 实现 Runnable 接口
public class Thread2 implements Runnable { | |
@Override | |
public void run() { | |
for (int i = 0; i < 10; i++) { | |
System.out.println(Thread.currentThread().getName() + ": " + i); | |
} | |
} | |
public static void main(String[] args) { | |
for (int i = 0; i < 10; i++) { | |
System.out.println(Thread.currentThread().getName() + ": " + i); | |
if (i == 2) { | |
Thread2 thread2 = new Thread2(); | |
new Thread(thread2).start(); | |
new Thread(thread2).start(); | |
} | |
} | |
} | |
} |
# 实现 Callable 接口
FutureTask 类包装 Callable 对象时,封装了 Callable 对象的 call () 方法的返回值。
class Thread3 implements Callable { | |
@Override | |
public Integer call() throws Exception { | |
int i = 0; | |
for (; i < 10; i++) { | |
System.out.println(Thread.currentThread().getName() + ": " + i); | |
} | |
return i; | |
} | |
public static void main(String[] args) { | |
Thread3 thread3 = new Thread3(); | |
FutureTask<Integer> futureTask = new FutureTask<Integer>(thread3); | |
for (int i = 0; i < 10; i++) { | |
System.out.println(Thread.currentThread().getName() + " :" + i); | |
if (i == 2) { | |
new Thread(futureTask, "有返回值的线程").start(); | |
} | |
} | |
try { | |
System.out.println("子线程返回值: " + futureTask.get()); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} catch (ExecutionException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
# 三种方式优缺点
采用实现接口(Runnable 和 Callable)的方式,线程类还可以继承其他的类。实现接口的线程对象还可以用来创建多个线程,可以实现资源共享。缺点是不能使用 this 指针来获取线程的名字等。
采用继承 Thread 类的方式,线程不能继承其他的类,但是 Thread 类中有 getName 方法,因为可以直接使用 this.getName () 来获取当前线程的名字。