Java 创建线程的3种方法及各自的优点
1.继承Thread类,然后调用start方法。
classMyThreadextendsThread{ //重写run方法,线程运行后,跑的就是run方法 publicvoidrun(){ //System.out.println(""); } publicstaticvoidmain(String[]args){ Threadt1=newMyThread(); t1.start();//线程运行,调用的run()方法. } }
2.实现Runnable接口的run方法,然后再用Thread类包裹后,调用start方法。
classTestThreadimplementsRunnable{ @Override publicvoidrun(){ //implementrunmethodhere //System.out.println(""); } publicstaticvoidmain(){ finalTestThreadobj=newTestThread(); Threadt1=newThread(obj); t1.start(); } }
3.实现Callable接口的call方法,用FutureTask类包裹Callable对象。然后再用Thread类包裹FutureTask类,并调用start方法。call()方法可以有返回值。
classMyCallableimplementsCallable{ @Override publicIntegercall()throwsException{ intsum=0; for(inti=1;i<=100;i++){ sum+=i; } returnsum; } publicstaticvoidmain(String[]args)throwsException{ MyCallablemc=newMyCallable();//实例化callable FutureTaskoneTask=newFutureTask(mc);//用FutureTask包裹 ThreadoneThread=newThread(oneTask);//用Thread包裹 oneThread.start(); System.out.print(oneTask.get());//获取返回值 } }
Callable方法在Java8后,支持拉姆达表达式的写法,可以创建一个FutureTask类,语句上不是太罗嗦。Callable方式有以下几个优点:
- 可以捕获线程上的异常。
- 可以通过get方法得到返回值。
- get方法阻塞当前线程,直到调用的线程运行结束。
- 可以取消线程的运行。
下面代码演示了使用FutureTask类运行线程,捕获异常的例子:
FutureTasktask=newFutureTask (()->{ thrownewException("自定义异常"); }); newThread(task).start(); try{ System.out.println(task.get()); }catch(Exceptione){ System.out.println(e.getMessage()); }
Java6之后,还可以通过创建线程池来创建线程,使用ExecutorService的execute方法:
ExecutorServicees=Executors.newCachedThreadPool(); Runnabler=; es.execute(r);
实现Runnable接口相对于继承Thread类的优势:
(1)适合多个相同程序代码的线程去处理同一资源的情况
(2)可以避免由于java单一继承带来的局限性
(3)用接口的方式将你的代码和线程实现分离,更加清晰。
(4)通过继承Thread类,每个线程都有一个相关联的唯一对象,而实现Runnable接口,多线程可以共享同一个Runnable实例。
(5)增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。
以上就是Java创建线程的3种方法及各自的优点的详细内容,更多关于JAVA创建线程的资料请关注毛票票其它相关文章!