JAVA创建线程的三种方式
JAVA创建线程的三种方式
一、JAVA创建线程的方式
JAVA中为了有异步计算,所以需要开启线程帮助后来计算,后台运行,在java中开启线程的方式有三种:
- 继承Thread类
- 实现Runnable接口
- 使用Callable和Future
二、线程创建方式的异同
- 继承Thread类: (1)通过Thread的构造方法创建线程 (2)通过start启动线程线程,且一个线程只能执行一次 (3)调用this.即可获得当前线程 (4)若要两个线程之间共享变量时,需要在声明为static变量,不推荐使用static变量,因为异步问题不容易控制。
- 实现Runnable接口 (1)线程只是实现了Runnable接口,还可以继承其他类和实现其他接口; (2)可以多个线程之间共享同一个目标对象(Runnable),非常适合多个线程处理同一份资源的情况;这一点比较难理解,看下面的代码示例会好理解。 (3)使用Thread.currentThread()可获得当前线程
- FutureTask:使用Callable和Future (1)Callable接口是Runnable接口的增强版 (2)Callable接口中的call()方法可以有返回值,也可以声明抛出异常
实现Runnable接口和继承Thread的方式区别: 继承Thread创建的线程是创建的Thread子类即可代表线程对象;而实现Runnable接口的创建的Runnable对象只能作为线程对象的target。 这也就是Runnable可以共享数据的原因。
FutureTask、Callable、Future之间的关系: 它实现了了RunnableFuture接口,而RunnableFuture接口又继承自Runnable和Future接口,所以FutureTask既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
public class FutureTask<V> implements RunnableFuture<V> {
}
三、实践
3.1 继承Thread类
class Test {
public static int number = 0;
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();
TestThread2 testThread2 = new TestThread2();
testThread2.start();
}
public static class TestThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
System.out.println(this.getName() + ":" + ++number);
}
}
}
public static class TestThread2 extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
System.out.println(this.getName() + ":" + ++number);
}
}
}
}
3.2 实现Runnable接口
该代码示例中是两个线程共用一个Runnable,其中Runnable的数据是两个线程之间共享的。
class Test {
public static void main(String[] args) {
TestRunnable testRunnable = new TestRunnable();
// 共用一个Runnable,数据会按顺序输出
new Thread(testRunnable).start();
new Thread(testRunnable).start();
}
public static class TestRunnable implements Runnable {
int number = 0;
@Override
public void run() {
++number;
System.out.println(Thread.currentThread().getName() + " " + number);
}
}
}
3.3 FutureTask:使用Callable和Future
class Test {
public static void main(String[] args) {
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>) () -> {
int i = 0;
while (i < 10) {
++i;
}
//call()方法的返回值
return i;
});
new Thread(task, "有返回值的线程").start();
try {
System.out.println("task.get():" + task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}