java创建线程的三种方式:
- 继承Thread类创建线程类
- 通过Runable接口创建线程类
- 通过Callable和FutureTask创建线程
总结下:
实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值。
1、如果需要访问当前线程,必须调用Thread.currentThread()方法。
2、继承Thread类的线程类不能再继承其他父类(Java单继承决定)。
注:一般推荐采用实现接口的方式来创建多线程
参考代码:MyThread RunnableThreadTest CallableThreadTest ExecutorServiceTest
//继承Thread类
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(getName());
}
public static void main(String[] args) {
for(int i=0;i<10;i++){
new MyThread().start();
}
// 内部类 方式
new Thread(){
@Override
public void run() {
for (int x = 0; x < 10; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}.start();
}
}
// 实现runnable接口
public class RunnableThreadTest implements Runnable {
public void run() {
System.out.println("run:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
System.out.println("main:"+ Thread.currentThread().getName());
RunnableThreadTest rt = new RunnableThreadTest();
new Thread(rt, "线程1").start();
// 用内部类的方式创建线程,实现runnable接口
new Thread(new Runnable() {
@Override
public void run() {
for (int x = 0; x < 10; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}).start();
}
}
/**
* 实现Callable接口
* 1】创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。
2】使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
3】使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)
4】调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
*
*/
public class CallableThreadTest implements Callable<Integer> {
public static void main(String[] args) {
CallableThreadTest ctt = new CallableThreadTest();
FutureTask<Integer> ft = new FutureTask<Integer>(ctt);
System.out.println(Thread.currentThread().getName() + "===== ");
new Thread(ft, "有返回值的线程").start();
try {
System.out.println("子线程的返回值:" + ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override
public Integer call() throws Exception {
for (int i=0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return 20;
}
}
// 用线程池的方式创建线程,并获得返回值
// Java线程池结合Future、Callable获得线程返回结果
public class ExecutorServiceTest {
private final int NUMBER = 4;
public void ExecutorService() {
// 创建容量为NUMBER的线程池。
ExecutorService pool = Executors.newFixedThreadPool(NUMBER);
// 接收返回值结果
ArrayList<Future<String>> futures = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++) {
// 自己的业务线程,实际工作中改成对应的业务逻辑
AThread t = new AThread(i);
Future<String> f = pool.submit(t);
futures.add(f);
}
System.out.println("....开始获取结果中...");
// Future的get方法在获取结果时候将进入阻塞,阻塞直到Callable中的call返回。
for (Future<String> f : futures) {
try {
// if(f.isDone())
System.out.println(f.get());
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(".....结束得到结果....");
// 关闭线程池。
pool.shutdown();
}
public static void main(String[] args) {
new ExecutorServiceTest().ExecutorService();
}
// 业务线程
private class AThread implements Callable<String> {
// 可做为参数传过来
private int id;
public AThread(int id){
this.id = id;
}
@Override
public String call() {
// 执行相应的逻辑
System.out.println("线程:" + id + " 运行..");
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程:" + id + " -> 结束.");
return "返回的字符串" + id;
}
}
}