Java中有四种实现多线程的方式
一、继承了Thread类创建线程
- 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体
- 创建Thread子类的实例,即创建线程对象
- 调用线程对象的start()方法来启动该线程。
class MyThread extends Thread{
public void run(){
////////
}
}
public class Main{
public static void main(String[] args){
MyThread myThread = new MyThread();
myThread.start();
}
}
二、通过Runnable接口创建线程类
- 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
- 调用线程对象的start()方法来启动该线程
class MyThread implements Runnable{
public void run() {
/////
}
}
public class Main{
public static void main(String[] args){
MyThread mt = new MyThread();
new Thread(mt).start();
}
}
三、通过Callable和Future来创建线程
- 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
- 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
- 使用FutureTask对象作为Thread对象的target创建并启动新线程
- 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
class MyThread implements Callable {
public Object call() throws Exception {
/////
}
}
public class Main{
public static void main(String[] args) throws ExecutionException,InterruptedException {
FutureTask<String> task = new FutureTask<>(new MyThread());
new Thread(task).start();
new Thread(task).start();
System.out.println(task.get());
}
}
四、通过线程池创建线程
利用线程池不用new就可以创建线程,线程可复用,利用Executors创建线程池。
1.线程池的实现原理
2.线程池的实现与设计
Java中的Runnable和Callable有什么不同
- Callable定义的方法是call(),而Runnable定义的方法是run();
- Callable的call()有返回值,而Runnable的run()没有返回值;
- Callable的call()可以抛出异常,而Runnable的run()方法不可以抛出异常。
一个类是否可以同时继承Thread类和实现Runnable接口
可以。因为Main类中从Thread类中继承了run()方法,这个run()方法可以被当做Runnable接口的实现。
public class Main extends Thread implements Runnable{
public static void main(String[] args){
Thread thread = new Thread(new Main());
thread.start();
}
}