Java多线程的四种实现方式
线程的生命周期
Java中线程有六种生命状态,可通过源码查看。
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
实现多线程的四种方式
1、继承Thread类的方式
public class Demo01 {
public static void main(String[] args) {
//创建线程对象
MyThread mt = new MyThread();
//调用start方法,开启线程
mt.start();
for (int i = 1; i <= 100; i++) {
//主线程运行该命令
System.out.println("main" + i);
}
}
}
//定义一个线程类
class MyThread extends Thread {
//重写run方法,定义线程运行的内容
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println("MyThread" + i);
}
}
}
2、实现Runnable接口的方式
public class Demo02 {
public static void main(String[] args) {
//创建任务类对象
MyTask mt = new MyTask();
//创建线程类对象
Thread t = new Thread(mt);
//开启新线程
t.start();
for (int i = 1; i <= 100; i++) {
System.out.println("main" + i);
}
}
}
//定义一个任务类,实现Runnable接口
class MyTask implements Runnable {
//重写run方法,用于定义任务的执行内容
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println("MyTask" + i);
}
}
}
Thread类方式与Runnable接口方式的比较
1、复杂程度
继承Thread类的方式简单一些
实现Runnable接口的方式复杂一些
2、源码原理:
1、继承Thread类:调用start之后,访问底层的start0,start0是一个本地方法,java代码中看不到,start0返回来调用了当前线程对象的run方法,run方法已经被我们重写过了
2、实现Runnable接口:创建Thread类型的对象,传入了一个Runnable的实现类对象,参数对象给Thread中的一个成员变量target赋值,这个target就是当前线程要运行的任务。调用Thread中的start方法,start调用本地方法start0,start0返回来调用当前Thread对象的run方法,判断target是否为空,如果不为空,就运行target的run,这个run已经被我们重写,所以最终运行的是重写之后的内容
3、设计:
1、继承Thread类:不太方便,java中不支持多继承,一旦某个类为了实现多线程,继承了Thread类,无法再继承其他类型
2、实现Runnable接口:比较方便,java中支持多实现,一个代码为了实现多线程,可以在实现Runnable接口的前提下,继承其他的类型
4、灵活性:
1、继承Thread类:灵活性不太好,将线程和任务绑定在了一起,无法分离
2、实现Runnable接口:灵活性比较好,线程和任务没有完全绑定在一起;一条线程可以执行任意任务,一个任务可以选择线程来执行,甚至可以被多条线程同时执行,也可以被线程池执行,可以让数据在多条线程中被共享
3、线程池实现方式
不推荐使用Executors创建线程池,推荐使用ThreadPoolExecutor创建线程池
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo03 {
public static void main(String[] args) {
// 获取线程池
ExecutorService es = Executors.newFixedThreadPool(3);
//提交一个任务类对象到线程池中,让线程池中的线程来完成这个任务
es.submit(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 999; i++) {
System.out.println(Thread.currentThread().getName() + "..." + i);
}
}
});
es.submit(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 999; i++) {
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
});
es.submit(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 999; i++) {
System.out.println(Thread.currentThread().getName() + "******" + i);
}
}
});
es.submit(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 999; i++) {
System.out.println(Thread.currentThread().getName() + "&&&&" + i);
}
}
});
//关闭线程池,暂停尚未执行的任务
List<Runnable> list = es.shutdownNow();
System.out.println(list.size() + "%%%");
}
}