Java创建线程有两种方法,一种是继承Thread,另一种实现Runnable或Callable接口。
一,继承Thread
public class APP { public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { int i = 0; while (i < 100) { System.out.println(i++); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; thread.start(); } }
上述例子通过重写Thread的run方法,来定时输出i的值,但是要主要Thread的run方法仅仅是个普通的方法,必须要通过调用start方法才能创建线程去执行run方法,直接调用run就没有线程的创建了。
二,实现Runnable或Callable接口来创建线程。
这两个接口的实现只能是变成一个普通的类,要创建线程都必须要通过其他相关类开启的。
这两个接口最大的区别:Callable有返回值且能抛出受检测异常,而Runnable没有返回值也无法抛出受检测异常;
1,对于Runnable接口来说,
要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过Executor
public class APP { public static void main(String[] args) { class MyRunnable implements Runnable { @Override public void run() { System.out.println("start -> " + Thread.currentThread().getName()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("end -> " + Thread.currentThread().getName()); } } Thread thread = new Thread(new MyRunnable()); thread.start(); Executor executor = Executors.newSingleThreadExecutor(); executor.execute(new MyRunnable()); } }
2,对于Callable接口来说,
要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过ExecutorService,但是都要同时借助于Future接口来实现对Callable返回值的相关控制。这里的ExecutorService接口是继承了Executor接口的,它增加了一些功能,大家可以点开源码看看就知道,而实例化都是通过Executors类的静态方法来实现的。
2.1 通过Thread去创建
由于Thread只能接受Runnable所以要想通过Thread去创建Callable线程,还要再借助一个即继承了Callable接口也继承了Runnable接口的类,这个类就是FutureTask。
2.2 通过ExecutorService去创建
由于ExecutorService天然支持Callable接口,所以直接submit就可以了。
public class APP { public static void main(String[] args) throws Exception { class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { Thread.sleep(3000); System.out.println("end"); return 200; } } ExecutorService es = Executors.newCachedThreadPool(); Future<Integer> future = es.submit(new MyCallable()); System.out.println("when ExecutorService -> " + future.get()); FutureTask<Integer> task = new FutureTask<Integer>(new MyCallable()); Thread thread = new Thread(task); thread.start(); System.out.println("when Thread ->" + task.get()); } }
备注:
Future的get方法是线程阻塞的,直到Callable的call()方法返回值为止。
再次提醒创建线程不要直接调用run方法。
如果发现理解不了,最好点进去看看源码。