有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)); } }