一、继承Thread类
继承Thread类并重写run方法。
代码:
public class MyThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("extends Thread");
}
}
public class App
{
public static void main( String[] args )
{
MyThread myThread = new MyThread();
myThread.start();
System.out.println("运行结束");
}
二、实现Runnable接口
Java不支持多继承,如果线程类已经有了一个父类,就不能再继承Thread类了,可以实现Runnable接口,Thread类也是实现了Runnable接口的。
public class MyThread2 implements Runnable {
public void run() {
System.out.println("implements Runnable");
}
}
public class App
{
public static void main( String[] args )
{
Runnable myRunnable = new MyThread2();
Thread myThread = new Thread(myRunnable);
myThread.start();
System.out.println("运行结束");
}
}
无论是通过继承Thread还是实现Runnable接口,都需要通过start()方法来启动线程,当然,调用了start()方法只是让线程进入就绪状态(可运行状态),表示随时可以运行,等待调度程序选中,选中后便获取了CPU时间片,开始执行run()方法。
如果是直接调用run方法,那么是由当前线程调用了run方法,那么就不是异步执行了,而是同步执行。
三、使用Callable和Future
- 创建Callable接口的实现类,并实现call()方法;
- 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callback对象的call()方法的返回值,该类实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable, Future接口;
- 使用FutureTask对象作为Thread对象的target创建并启动新线程;
- 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
public class MyCall implements Callable<String> {
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
public class App
{
public static void main( String[] args )
{
Callable<String> callable = new MyCall();
FutureTask<String> future = new FutureTask<String>(callable);
Thread thread = new Thread(future);
thread.start();
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("运行结束");
}
}
使用get方法可以获得线程执行后的返回值,但是该方法是阻塞的,调用该方法会一直等待返回值。