(线程类已经继承Thread类,则无法继承其他类;每个线程都需要创建不同的Thread类,多个线程间无法共享线程类的实例变量)
public class HelloWorldThread extends Thread{ @Override public void run() { System.out.println("Hello world!"); } public static void main(String[] args) { Thread thread = new HelloWorldThread(); thread.start(); } }(Thread对象是真正的线程,实现类只是线程的执行体)
public class HelloWorldThread implements Runnable{ @Override public void run() { System.out.println("Hello world!"); } public static void main(String[] args) { Thread thread = new Thread(new HelloWorldThread()); thread.start(); } }继承Thread类和实现Runnable的方式没有返回值,也无法抛出异常,如何判断线程是否执行完成,了解任务执行情况,取消任务的执行,这就需要Callable和Future来创建线程
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。使用FutureTask对象作为Thread对象的target创建并启动新线程。调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。Callable类似于Runnable接口的增强版,其提供的call()方法将作为线程的执行体,同时允许有返回值。但是Thread类的target参数是Runnable类型。
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }这时就需要借助 Future接口,此接口可以接受call() 的返回值,RunnableFuture接口是Future接口和Runnable接口的子接口,可以作为Thread对象的target ,并且, Future 接口提供了一个实现类:FutureTask 。
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }FutureTask实现了RunnableFuture接口,可以作为 Thread对象的target。
public class CallableTest implements Callable<Integer> { @Override public Integer call() throws Exception { Random random = new Random(); Integer add = 0; for (int i = 0; i < 100; i++) { add = add + i; } System.out.println("CallableTest:" + add); return add; } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask<>(new CallableTest()); Thread thread = new Thread(futureTask); thread.start(); System.out.println(futureTask.get()); } }FutureTask是一个包装器,使用FutureTask类来包装Callable对象,它通过接受Callable来创建,调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
最后我们来分析下Future接口
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。isDone方法表示任务是否已经完成,若任务完成,则返回true。get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回。get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。