文章目录该文章属于JavaSE应掌握的部分,属于并发编程的基础
本人能力有限,如有遗漏或错误,敬请指正,谢谢
- 一、继承Thread类
- 二、实现Runnable接口
- 2.1 通过匿名内部类的方式传递
- 2.2 Lambda写法
- 三、实现Callable接口
- 3.1 与Runnable接口的区别
- 3.2 使用方法
创建一个类继承Thread类后,该类重写run()方法,表示这个类是一个线程类
public class MyThread extends Thread{ //线程调用的方法 @Override public void run(){ } }
创建线程实例,调用start()方法开启线程(不是run()方法)
public static void main(String[] args){ //创建MyThread对象 MyThread my1=new MyThread(); //启动线程 my1.start(); try { Thread.sleep(5000);//线程睡眠5秒 } catch (InterruptedException e) { e.getMessage(); } System.out.println("主线程main结束"); }
总结:由于Java的继承是单继承,所以往往在项目中如果某个类需要继承一个抽象类重写方法,那么就不能继承Thread类了。(一般不使用,往往是学习中的第一个创建线程方式)
二、实现Runnable接口创建一个类通过实现Runnbale接口,并重写其的run()方法
public class MyThread2 implements Runnbale{ //线程执行的方法 public void run(){ } }
创建Thread对象后,将该类作为参数传递进去
注意:创建的Thread对象才是我们的线程对象,而线程执行的run方法则是调用传递参数里的run()方法
public static void main(String[] args){ MyThread2 myThread2=new MyThread2(); //创建Thread对象,传递参数 Thread thread=new Thread(myThread2); thraed.start();//启动线程 try { Thread.sleep(5000);//线程睡眠5秒 } catch (InterruptedException e) { e.getMessage(); } System.out.println("主线程main结束") }2.1 通过匿名内部类的方式传递
好处:不用多创建一个类,直接在创建Thread对象时通过匿名内部类的方式重写run()方法
public static void main(String[] args){ //创建Thread对象,传递匿名参数 Thread thread=new Thread(new MyThread2(){ @Override public void run(){ //方法实现 } }); thraed.start();//启动线程 }2.2 Lambda写法
好处:以上写法的简洁写法,Jdk1.8以上版本
public static void main(String[] args){ Thread thread=new Thread(() -> { //方法实现 }); }
总结:由于Java是可以实现多接口的(为了弥补单继承),所以创建线程可以采用这种方式,不会影响到普通类的继承
三、实现Callable接口 3.1 与Runnable接口的区别在Callable接口中的call()方法作用是和run()一样的,是线程执行时调用的方法
3.2 使用方法优势在于:
1、从图中可以看出call()方法里有throws Exception,所以call()方法可以抛出异常,被外面的操作捕获,获取异常的信息
2、call()方法可以有返回值,所以我们在编写业务代码的时候,可以获取返回值
3、call()的返回值是泛型
由于new Thread()里面的参数只能是Runnable类型,所以不能直接创建Callable实现类,那么需要有一个既实现了Callable接口又实现了Runnable接口的类FutureTask
FutureTask
①因为call()方法有返回值,那么在线程中获取返回值的方法,用FutureTask中的get()方法
②可以传递泛型,指定返回的类型
③FutureTask同时实现了Runnable、Future接口,它既可以作为Runnable被线程执行,也可以得到Callable的返回值。
④可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果
1.先创建FutureTask对象 2.用匿名内部类重写call方法=新建类实现Callable接口 3.将FutureTask对象作为参数传入Thread类中 4.启动线程,接受返回值用方法:futureTask.get() public static void main(String[] args) throws InterruptedException, ExecutionException { //指定返回值为String FutureTaskfutureTask=new FutureTask(new Callable() { @Override public String call() throws Exception { return "thread线程call()方法返回值"; } }); //传入参数 Thread t1=new Thread(futureTask); t1.start(); String result=futureTask.get();//接受返回值 System.out.println(result); }
关键点:使用get()方法会导致当前线程阻塞,只有结束方法才会执行主线程
总结:实现Callable接口功能比第二种方式更为强大,可以判断线程是否执行完毕或者接收返回值