2. Java多线程的实现方式
① 实现Runnable
接口
- 实现Runnable接口中的run方法,将Runnable实例作为Thread新建对象的参数,然后调用 Thread对象的start() 方法,启动一个新的线程。
- 注意: 实现
Runnable
和 Callable 接口
的类只能当做一个可以在线程中运行的任务
,不是真正意义上的线程
。因此最后还需要通过 Thread 来调用,可以说任务是通过线程驱动从而执行
的。 - 具体的代码:
class MyRun implements Runnable {
@Override
public void run() {
System.out.println("实现Runnable接口的run方法");
}
}
public class RunThread {
public static void main(String[] args) {
MyRun myRun = new MyRun();
Thread thread = new Thread(myRun);
thread.start();
}
}
② 继承Thread
类
- 继承
Thread
类,重写其中的run()方法。创建子类的实例,调用从Thread类继承来的start()方法,启动一个新的线程。 - 具体的代码:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("重写Thread类的run方法");
}
}
public class RunThread {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
③ 实现Callable
接口
- 与 Runnable 相比,
Callable 可以有返回值
,返回值通过 FutureTask 进行封装
。 - 先实现Callable接口的call()方法,然后将封装好Callable接口实例的FutureTask实例传入Thread,由Thread对象进行驱动
- 具体代码:
class MyCall implements Callable<String> {
@Override
public String call() throws Exception {
return "Hello world!";
}
}
public class RunThread {
public static void main(String[] args) {
try {
MyCall myCall = new MyCall();
FutureTask<String> task = new FutureTask<>(myCall);
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
}
}
- 注意: FutureTask的get方法会产生
ExecutionException
和InterruptedException
两种异常,需要通过try-catch进行处理。
④ run方法和start方法的区别
class MyThread extends Thread {
@Override
public void run() {
System.out.println("重写Thread类的run方法");
}
}
public class RunThread {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.run();
}
}
- 起初你并不会感觉到有什么不妥,因为 run()方法的确如你所愿的被调用了。
- 事实上,run()方法并非是由刚创建的myThread线程所执行的,而是被创建新线程的主线程所执行。想要让创建的myThread线程执行 run()方法,必须调用myThread线程的 start()方法。