java线程创建
前提:无论如何创建多线程,开启线程必须使用Thread类的方法Start(),同时一个线程的start()方法,只能被调用一次,执行多次会抛出异常 IllegalThreadStartException ,所有的线程最开始被初始化为0。
- 第一种(第一种创建)、 创建类继承Thread类,然后覆写run方法(线程任务)。
开启线程:直接使用Thread.start() 方法 - 第二种(第二种创建)、 实现Runable接口,然后覆写run方法。
开启线程:Thread 类中有 Thread(Runnable) 构造方法,可以传入一个Runnable对象(实际上是实现了Runnable接口的类对象),把它变为Thread类型。
public class Thread implements Runnable;//java的抽象任务线程
class MyThread implements Runnable;//我们实际的任务线程
两个子类都实现了Runnable,代理模式:在Thread类中完成对线程的资源准备工作(辅助工作),然后在我们自己的类中实现具体的线程任务(真实业务)。
对比:
1、继承Thread 类有单继承局限,而实现Runnable接口 则更加灵活,并且真实的Thread类也可以辅助真实线程类。
2、实现Runnable接口可以更好的实现程序共享的概念(继承Thread也可以,但是稍微麻烦) 。
第三种、 实现Callable接口,而后覆写call方法。(最大的区别:执行完线程任务后有返回值)
Future类: 有一个 get()方法可以接收Callable接口的返回值。
开启线程:如图中我们可以看到,FutureTask类相当于实现了Future 和Runable两个接口,并且FutureTask有一个可以传入Callable对象(也是实现Callable接口的类)的构造方法,所以就可以通过这种方式来开启线程:
//产生Callable对象
CallableTest test = new CallableTest();
//产生FutureTask对象
FutureTask<String> futureTask = new FutureTask<>(test);
//产生Thread对象
Thread thread = new Thread(futureTask);
//做这三步主要是因为 所有的线程启动只能是使用Thread的start()方法。
thread.start();
System.out.println(futureTask.get());//打印返回值
第四种:线程池