实现子线程的三种方式:
1.继承Thread类,重写run方法。
2.实现Runnable接口,重写run方法。 优点:因为Runnable是接口,所以可以实现"多继承";将run方法中的具体线程业务逻辑和Thread线程的开启控制解耦。 (run方法没有返回值)
3.实现Callable接口,重写call方法。 可以有返回值(线程任务的执行结果)。
Callable接口实现多线程(线程池版):
Demo.java:
package cn.xxx.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/*
* 实现线程程序的第三个方式,实现Callable接口方式
* 实现步骤
* 工厂类 Executors静态方法newFixedThreadPool方法,创建线程池对象
* 线程池对象ExecutorService接口实现类,调用方法submit提交线程任务
* submit(Callable c)
*/
public class Demo {
public static void main(String[] args)throws Exception {
ExecutorService es = Executors.newFixedThreadPool(2);
//submit方法提交线程任务,返回 Future接口实现类的对象
Future<String> result = es.submit(new ThreadPoolCallable()); // 返回的Future表示线程执行的结果。 submit可以传Runnable接口,也可以传Callable接口
String s = result.get(); // 从Future中获取结果。
System.out.println(s);
es.shutdown(); // 关闭线程池。 (不经常用)
}
}
ThreadPoolCallable.java(实现Callable接口,重写call方法):
package cn.xxx.demo;
/*
* Callable 接口的实现类,作为线程提交任务出现
* 使用方法返回值
*/
import java.util.concurrent.Callable;
public class ThreadPoolCallable implements Callable<String>{ // 实现Callable接口
public String call(){ // 重写call方法。 可以有返回值
return "abc"; // 可以有返回值。 线程池中用Future接口实现类接收结果。
}
}
Callable接口实现多线程(未使用线程池):
CallableTest.java:
package cn.xxx.juc;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
class MyCall implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+" Come in call");
//睡5秒
TimeUnit.SECONDS.sleep(5);
//返回200的状态码
return 200;
}
}
public class CallableTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建MyThread对象
MyCall myCall = new MyCall();
//创建未来任务对象
FutureTask<Integer> futureTask = new FutureTask<>(myCall); // FutureTask实现了Future接口和Runnable接口,是Callable与Runnable之间的桥梁
//创建处理未来任务的线程(多线程)
new Thread(futureTask, "未来任务名").start();
System.out.println(Thread.currentThread().getName()+"主线程继续");
//获取未来任务的结果(Callable的返回值)
Integer result = futureTask.get(); // get()方法会阻塞当前线程
System.out.println(result);
Integer result2 = futureTask.get(); // 多次调用get()并不会重新执行耗时的未来任务
System.out.println(result2);
}
}