线程创建方式
方式一: 继承Thread类
-
定义Thread的子类,重新Thread类中的run 方法,该方法即为该线程所要完成的"任务",所以将run方法称之为"执行体"
-
创建Thread的子类,即为创建了一个线程的实例,即创建了线程对象
-
调用线程的启动方式,即线程对象的start()方法启动线程
方式二: 实现Runnable接口
-
定义Runnable接口的实现类,并重写run()方法,与Thread的run()方法效用一致,同为对应线程的"执行体"
-
创建Runnable实现类的实例,并通过该实例作为Thread的target(目标)来创建Thread对象,该Thread的对象才是真正的线程对象(实质还是通过Thread实现创建线程)
-
调用线程的start()方法启动线程
方式三: 实现Callable 接口与Future
Callable 是增强型的Runnable , 因为Callable带有返回值,并且可以抛出异常
- 创建Callable接口,并实现其call()方法,该方法不仅与run()方法效用相同,作为线程的"执行体",且拥有返回值,返回值类型即为传入的泛型类型
@FunctionalInterface public interface Callable<V> { V call() throws Exception; }
- 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象方庄了该Callable对象的call()方法的返回值
FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口
- 使用FutureTask对象作为Thread对象的target创建并启动新线程
public class Demo implement Callable<Integer>{ @Override public Integer call(){......} } public class Test{ public static void main(String args){ FutureTask<Integer> ft = new FutureTask(new Demo); //传入执行的线程及线程名,真正创建线程,并启动线程 new Thread(ft,"用有返回值的线程").start(); //返回值 Integer i = ft.get(); } }
- 调用FutureTask对象的get()方法来回的子线程执行结束后的返回值
- 调用FutureTask的对象的get()方法,获取对应子线程执行结束后的返回值