1、多线程的实现方式有下面四种:
(1)继承Thread类,重写run()方法;
(2)实现Runnable接口,重写run()方法;
(3)通过Callable和Future创建线程,重写call()方法;
(4)通过线程池创建线程(扩展,本篇文章不做讨论)。
2、下面看它们各自的代码实现
2.1 继承Thread类
实现流程:
(1)继承Thread类并重写run方法;
(2)创建线程对象;
(3)调用该线程对象的start()方法来启动线程。
代码实现:
class ThreadTest extends Thread {
public int a = 10;
@Override
public void run() {
while (a>0){
System.out.println(this.getName() + ":" + a--);
}
}
}
public class Multithreading {
public static void main(String[] args) {
new ThreadTest().start();
new ThreadTest().start();
}
}
运行结果:
2.2 实现Runnable接口
实现流程:
(1)定义一个类实现Runnable接口,并重写该接口的run()方法;
(2)创建 Runnable实现类的对象,作为创建Thread对象的target参数,此Thread对象才是真正的线程对象;
(3)调用线程对象的start()方法来启动线程。
代码实现:
class RunnableTest implements Runnable{
private int a=10;
@Override
public void run() {
while (a>0){
System.out.println(Thread.currentThread().getName() + ": " + a--);
}
}
}
public class Multithreading {
public static void main(String[] args) {
RunnableTest runnable = new RunnableTest();
new Thread(runnable,"张三").start();
new Thread(runnable,"李四").start();
}
}
运行结果:
2.3 通过Callable和Future创建线程
实现流程:
(1)定义一个类实现Callable接口,并重写call()方法,该call()方法将作为线程执行体,并且有返回值;
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象;
(3)使用FutureTask对象作为Thread对象的target创建并启动线程;
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
代码实现:
class CallableTest implements Callable {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i=0;i<100;i++){
sum += i;
}
System.out.println(Thread.currentThread().getName()+": "+sum);
return sum;
}
}
public class Multithreading {
public static void main(String[] args){
CallableTest callableTest = new CallableTest();
FutureTask<Integer> futureTask = new FutureTask<>(callableTest);
new Thread(futureTask,"张三").start();
try{
System.out.println(futureTask.get());
}catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
运行结果:
3、三种方式实现的优缺点
3.1 继承Thread类:
优点:简单方便,访问当前线程无需使用 Thread.currentThread()方法,直接使用 this 即可获得当前线程。 缺点:受到java中单继承的限制,不能再继承其它类。
3.2 实现Runnable接口、通过Callable和Future创建线程一并讨论:
优点:(1)适合多个线程进行资源共享;
(2)可以避免java中单继承的限制;
(3)线程池只能放入Runable或Callable接口实现类,不能直接放入继承Thread的类。
缺点:编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法。
3.3 实现Runnable接口和通过Callable和Future创建线程两者的区别:
(1)Callable重写的是call()方法,Runnable重写的方法是run()方法;
(2)call()方法执行后可以有返回值和可以抛出异常,run()方法都不可以;
(3)运行Callable任务可以拿到一个Future对象,该线程对象可以通过get()方法得到call()方法的返回结果 。
读到这说明已经基本掌握多线程的创建及使用了,下篇文章将深入理解线程的概念、使用场景等?
本篇文章参考 Java创建线程的三种方式及对比 - 简书
本文为学习笔记,所参考文章均已附上链接,若有疑问请私信!
创作不易,如果对你有点帮助的话麻烦点个赞支持一下!
新手小白,欢迎留言指正!