任何情况下,只要定义了多线程,多线程的启动永远只有一种方案:Thread类中的start()方法
1.创建Thread的子类:
创建一个Thread的子类,并在Thread的子类中重写Thread类中的run方法,调用Thread类中的start方法,执行该线程
class MyThread extends Thread{
@Override
public void run() {
System.out.println("继承了Thread");
}
}
public class Main {
public static void main(String[] args){
MyThread thread=new MyThread();
thread.start();
}
}
每一个线程对象只允许启动一次,如果多次启动,则会抛出IllegalThreadStateException异常
2.实现Runnable接口:
使用Runnable接口创建多线程的好处:
-
避免了单继承的局限性
一个类只能继承一个类,但实现了Runnable接口可以继承其他类,实现其他接口 -
增强了程序的扩展性,降低了程序的耦合性
实现Runnable接口中把设置线程任务和开启线程任务进行了分离(解耦)
class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println("实现了Runnable接口");
}
}
public class Main {
public static void main(String[] args) {
RunnableImpl runnable=new RunnableImpl();
new Thread(runnable).start();//需要利用Thread的构造方法,用start启动多线程
}
}
同时Runnable也支持Lambda表达式,则可表示为
public class Main {
public static void main(String[] args) {
new Thread(()->{
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
}).start();
}
}
3.使用Callable方式
Callable定义时可以设置一个泛型,泛型的类型就是返回数据的类型,这样可以避免向下转型带来的安全隐患
Runnable与Callable的区别:
- Runnable是在JDK1.0的时候提出的多线程接口,而Callable是在JDK1.5之后提出的
- java.long.Runnable接口之中只提供有一个run()方法,并且没有返回值
- java.util.concurrent.Callable接口中提供有call()方法,可以有返回值
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
for(int i=0;i<10;i++){
System.out.println("线程执行"+i);
}
return "执行完毕";
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
FutureTask<String> task=new FutureTask<>(new MyThread());
new Thread(task).start();
}
}
4.匿名内部类创建线程:
public class Main {
public static void main(String[] args) throws InterruptedException {
//Thread类
//相当于:new MyThread().start();
new Thread(){
@Override
public void run(){
System.out.println(Thread.currentThread().getName());
}
}.start();//Thread-0
//Runnable接口
//相当于:Runnable r= new RunnableImpl();//多态
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
new Thread(r).start();//Thread-1
}
}