谈谈线程创建有哪些方式
- 1 继承Thread类重写run方法,然后调用自定义实例的start方法。
- 2 实现Runable接口重写run方法,将Runable实例封装为Thread实例并调用start方法。
- 3 实现Callable接口重写call方法,将Callable实例封装为FutureTask对象,进而封装为Thread对象并调用start方法。可以通过FutureTask对象get方法获取线程返回值。
- 4 使用线程池
- 方法1有单继承的局限性,自定义类继承了Thread不能继承其他类了。
- 方法2解决了单继承的局限性,而且将任务和线程分开了,一个Runable对象表示一个任务,可以将一个任务封装为多个线程,并且多个线程共享当前任务对象数据。
- 方法3支持线程有返回结果,运行Callable任务可以得到一个future对象,表示异步计算结果。
使用Thread类创建线程
- 自定义线程类继承Thread类,覆写run方法,通过调用子线程对象的start方法启动多线程。
- 实例
public class Test {
public static final Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
Thread thread1 = new Thread(){
@Override
public void run() {
for(int i=0;i<10;i++){
Test.log.info("i="+i);
}
}
};
thread1.start();
}
}
Runable结合Thread创建线程
- 将线程与可运行的任务分开。Runable实例对象表示任务,Thread对象表示线程。
- 首先实例化一个实现Runable接口的对象创建一个任务,然后实例化Thread对象将任务封装为线程,最后调用start方法进行执行。
- 示例
public class Test {
public static final Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
Job job1 = new Job();
Thread thread1 = new Thread(job1,"子线程1");
thread1.start();
}
}
class Job implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
Test.log.info("i="+i);
}
}
}
public class Test {
public static final Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
Runnable r = ()->{
for(int i=0;i<10;i++){
Test.log.info("i="+i);
}
};
new Thread(r,"子线程1").start();
}
}
- 一个runable对象也可以同时包装为多个线程对象,这样多个线程就会共享runable对象的数据。
- 在实例化Thread对象时可以传入一个Runable对象,当传入Runable对象后会将该对象作为Thread类的成员,在调用Thread对象的start方法时,会进行判断,如果当前Thread对象有Runable对象成员就执行Runable对象的run方法,否则就执行自己的run方法。
使用FutureTask创建线程
- Runable方法创建的线程是没有返回值的,使用FutureTask支持线程有返回值,可以在一个线程中获取另一个线程的返回结果。
- FutureTask类间接实现了Runable接口和Future接口,Future接口支持获取线程结果,Runable接口支持我们可以将当前对象封装为任务对象。
- 实现方式:传入一个callable对象,实例化FutureTask对象。然后将FutureTask对象包装为Thread线程对象,调用start方法执行。
- 示例
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println(1);
System.out.println(2);
System.out.println(3);
return "hello";
}
};
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread t = new Thread(futureTask);
t.start();
System.out.println(futureTask.get());