线程的几种实现方法
有三种使用线程的方法:
- 实现 Runnable 接口;
- 实现 Callable 接口;
- 继承 Thread 类。
实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。
Callable接口
class c implements Callable<String>{
@Override
public String call() throws Exception {
return null;
}
}
Runnable接口
class r implements Runnable{
@Override
public void run() {
}
}
Callable和Runnable的区别
相同点:
- 两者都是接口
- 两者都需要调用Thread.start启动线程
不同点:
- 核心方法、返回值不同(callable的核心是call方法,允许返回值,runnable的核心是run方法,没有返回值)
- call方法可以抛出异常,但是run方法不行
在使用过程中,Runnable可以直接放在Thread中启动,但是Callable需要借助FutureTask 来实现启动。
eg:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;
/**
* @author: dongyq
* @date: 2022/9/21 17:55
* @since:
* @功能描述:
*/
public class CallableTest implements Callable<String> {
private String string;
public CallableTest(String string) {
this.string = string;
}
@Override
public String call() throws Exception {
//任务阻塞5秒,异常向上抛出
Thread.sleep(5000);
return this.string;
}
public static void main(String[] args) throws Exception {
Callable<String> callable = new CallableTest("my callable is ok!");
FutureTask<String> task = new FutureTask<String>(callable);
long beginTime = System.currentTimeMillis();
//创建线程
new Thread(task).start();
//调用get()方法阻塞主线程
String str = task.get();
long endTime = System.currentTimeMillis();
System.out.println("hello :"+ str);
System.out.println("time :"+ (endTime - beginTime)/1000);
}
}
/**
* @author: dongyq
* @date: 2022/9/21 17:55
* @since:
* @功能描述:
*/
public class RunnableTest implements Runnable{
private String str;
public RunnableTest(String str) {
this.str = str;
}
@Override
public void run() {
try {
//线程休眠5s,有异常产生,只能内部解决,无法向上抛
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//5s之后输出
System.out.println("hello:" + this.str);
}
public static void main(String[] args) {
Runnable runnable = new RunnableTest("my runnable is ok");
Long beginTime = System.currentTimeMillis();
Thread thread=new Thread(()->{
runnable.run();
});
thread.start();
Long endTime = System.currentTimeMillis();
//先输出
System.out.println("time:" + (endTime-beginTime)/1000);
}
}