主题切换
创建线程
一、四种创建线程方式介绍
1. 继承Thread类
写法:自定义类继承Thread,重写run()方法,new对象后调用start()启动。 侧重:简单快速,适合一次性简单任务;缺陷是Java单继承,占用继承名额,无法再继承其他类。
2. 实现Runnable接口
写法:自定义类实现Runnable,重写run(),将实现类传入Thread构造器,调用start()。 侧重:解耦任务与线程,规避单继承限制;同一个任务对象可分给多个线程共享执行,无返回值,不能向外抛出异常。
3. 实现Callable接口
写法:实现Callable<V>重写call(),配合FutureTask包装,再传入Thread运行,通过get()拿返回结果。 侧重:支持异步返回结果、方法可抛出受检异常;适合需要获取线程执行结果的场景,使用比Runnable繁琐。
4. 线程池创建线程(项目主流)
写法:通过Executors或ThreadPoolExecutor创建线程池,submit()/execute()提交任务。 侧重:复用线程、控制并发数量、减少频繁创建销毁线程的开销,生产环境统一使用,支持Runnable/Callable两类任务。
二、四种方式核心区别
- 继承Thread:任务和线程耦合,单继承限制,无返回值,无法复用任务对象。
- 实现Runnable:任务与线程分离,支持多线程共用任务,无返回值、不能抛出异常。
- 实现Callable:有泛型返回值,方法可抛异常,必须搭配FutureTask使用,适合需要结果的异步任务。
- 线程池:统一管理线程,复用资源,控制并发,性能最优,企业开发标准方案。
三、面试高频问题解析
问:Java创建线程有哪四种方式?
答: ①继承Thread类;②实现Runnable接口;③实现Callable接口搭配FutureTask;④使用线程池创建线程。
问:Runnable和Callable有什么区别?
答: Runnable的run方法无返回值,不能抛出受检异常;Callable的call方法支持泛型返回值,允许抛出异常,需要配合FutureTask才能交给线程执行,可通过get()获取执行结果。
问:run()和start()方法有什么区别?
答: start()用于向操作系统申请创建新线程,内部会自动调用run(),一个线程对象仅能调用一次start();run()只是普通业务方法,直接调用只会在当前主线程同步执行代码,可重复调用,不会开启新线程。
问:继承Thread和实现Runnable哪个更好?
答: 优先使用实现Runnable。Java是单继承,继承Thread会占用唯一继承资格;Runnable将任务和线程解耦,同一个任务实例可以被多个线程共享,扩展性更强。
问:为什么项目中推荐使用线程池创建线程,不手动new Thread?
答: 频繁new Thread会频繁创建销毁线程,开销大且无并发管控;线程池可复用线程、限制最大并发数、统一管理任务队列、支持定时/周期任务,减少资源损耗,便于监控调优。