有3种实现方法,继承Thread类、实现Runnable接口、通过Callable接口实现多线程
1.1 继承Thread类
步骤:
1)继承Thread 类
2)重写父类run 方法
3)在run方法编写线程需求做的代码块
4)实例化线程类
5)调用线程start(启动线程)
public class ThreadDemo extends Thread{
/**
* 1.继承Thread类
* 2.重写run()方法
*/
@Override
public void run() {
System.out.println("我来了!~~~~~~");
}
public static void main(String[] args) {
ThreadDemo thread1 = new ThreadDemo();
ThreadDemo thread2 = new ThreadDemo();
thread1.start();//启动线程
thread2.start();//启动线程
//启动线程的唯一方法就是通过Thread类的start()实例方法。
//start()方法是一个native方法,它将启动一个新线程,并执行run()方法。
}
}
1.2 实现Runnable接口
步骤:
1)实现Runable 接口
2)重写父类run 方法
3)在run方法中编写线程需求做的代码块
4)实例化线程类
5)先实例化Thread再把线程通过构造方法传递调用线程start(启动线程)
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
}
//为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
1.3 通过Callable接口实现多线程
Java5之后,提供了Callable接口,看起来像是Runnable接口的增强版:该接口提供call()方法来作为线程执行体。与run()相比,call()方法更强大,该方法可以有返回值,并且可以声明抛出异常。
Callable接口介绍:
1)java.util.concurrent.Callable是一个泛型接口,只有一个call()方法
2)call()方法抛出异常Exception异常,且返回一个指定的泛型类对象
Callable接口实现多线程的应用场景:当父线程想要获取子线程的运行结果时
实现Callable和实现Runnable类似,但是功能更强大,具体表现在
a)可以在任务结束后提供一个返回值,Runnable不行;
b)call方法可以抛出异常,Runnable的run方法不行;
c)可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值).
使用Callable接口实现多线程的步骤
1)第一步:创建Callable子类的实例化对象
2)第二步:创建FutureTask对象,并将Callable对象传入FutureTask的构造方法中(注意:FutureTask实现了Runnable接口和Future接口)
3)第三步:实例化Thread对象,并在构造方法中传入FurureTask对象
4)第四步:启动线程
//实现Callable重写call方法
public class CallTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
return sum;
}
}
/**
* 创建多线程的方式 : 4种
* 1.继承Thread类
* 2.实现Runable接口
* 3.实现Callable接口
* 4.使用线程池创建线程
*
* Callable相比Runable的区别:
* 1. 线程任务有返回值
* 2. 需要使用FutureTask实现类接收返回值
* 3. futureTask.get方法获取放回值时, 主线程会进入阻塞状态, 等待分线程的完成
*/
public class CallableTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
CallTask callTask = new CallTask();
//使用FutureTask实现类接收返回值 泛型是返回值类型
FutureTask<Integer> futureTask = new FutureTask<>(callTask);
//new Thread(futureTask).start();
for (int i = 0; i < 100; i++) {
new Thread(futureTask).start();
}
// 主线程会进入阻塞状态, 等待分线程的完成 可以用于闭锁
Integer sum = futureTask.get();
System.out.println(sum);
long end = System.currentTimeMillis();
System.out.println("程序消耗时间: " + (end - start));
}
}