创建线程的四种方式
Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。
其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。
Runnable和Callable的区别
Runnable接口
public interface Runnable { void run(); } 1 2 3 Callable接口
public interface Callable<V> { V call() throws Exception; } 1 2 3 Runnable和Callable的区别
Runnable执行方法是run(),Callable是call() 实现Runnable接口的任务线程无返回值;实现Callable接口的任务线程能返回执行结果 call方法可以抛出异常,run方法若有异常只能在内部消化 注意
Callable接口支持返回执行结果,需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞! 如果线程出现异常,Future.get()会抛出throws InterruptedException或者ExecutionException;如果线程已经取消,会爬出CancellationException
Runnable示例
public class CallableDemo { public static void main(String[] args) { //创建一个定长的核心线程和最大线程数都是1的FixedThreadPool线程池 ExecutorService executorService = Executors.newFixedThreadPool(2);
Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(3000); System.out.println("Thread_current="+Thread.currentThread()); return "Hello world"; } }; System.out.println("start"); // 执行任务并获取Future对象 Future<String> future = executorService.submit(callable);
try{ //future.get()线程结果,会阻塞当前线程直到线程结束 System.out.println("future.get()="+future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }
System.out.println("end");
// 关闭线程池 executorService.shutdown(); } }
在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
避免点继承的局限,一个类可以实现多个接口 资源共享 Runnable接口和Thread之间的联系
public class Thread extends Object implements Runnable 由此可见:Thread类也是Runnable接口的子类