继承Thread类
定义一个线程类,重写实现run方法
(因为 Thread类也实现了 Runable接口),在其中定义线程要执行的任务(希望和其他线程并发执行的任务)。
当调用 start()方法
启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的run()方法
。
注:启动该线程要调用该线程的start方法,而不是run方法!!!
public class MyThread extends Thread {
public void run() {
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
}
package thread;
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t1 = new MyThread1();
Thread t2 = new MyThread2();
t1.start();
t2.start();
}
}
class MyThread1 extends Thread{
public void run(){
for (int i=0;i<1000;i++){
System.out.println("hello姐~");
}
}
}
class MyThread2 extends Thread{
public void run(){
for (int i=0;i<1000;i++){
System.out.println("来了~老弟!");
}
}
}
实现Runnable接口
需要实现run()方法
。通过 Thread 调用start()方法
来启动线程。
public class MyRunnable implements Runnable {
public void run() {
}
}
public static void main(String[] args) {
MyRunnable instance = new MyRunnable();
Thread thread = new Thread(instance);
thread.start();
}
package thread;
public class ThreadDemo2 {
public static void main(String[] args) {
Runnable r1 = new MyRunnable1();
Runnable r2 = new MyRunnable2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
class MyRunnable1 implements Runnable{
public void run() {
for (int i=0;i<1000;i++){
System.out.println("你是谁啊?");
}
}
}
class MyRunnable2 implements Runnable{
public void run() {
for (int i=0;i<1000;i++){
System.out.println("开门!查水表的!");
}
}
}
实现Callable接口
与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。
public class MyCallable implements Callable<Integer> {
public Integer call() {
return 123;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable mc = new MyCallable();
FutureTask<Integer> ft = new FutureTask<>(mc);
Thread thread = new Thread(ft);
thread.start();
System.out.println(ft.get());
}
匿名内部类形式的线程创建
package thread;
public class ThreadDemo3 {
public static void main(String[] args) {
Thread t1 = new Thread(){
public void run(){
for(int i=0;i<1000;i++){
System.out.println("你是谁啊?");
}
}
};
Runnable r2 = ()->{
for(int i=0;i<1000;i++){
System.out.println("我是查水表的!");
}
};
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
实现接口 VS 继承Thread
实现接口会更好一些,因为:
- Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
- 类可能只要求可执行就行,继承整个 Thread 类开销过大
到底有几种创建线程的方式?
我们先看下 JDK 源码中对 Thread 类的一段解释,如下图。
所以,我们也可以这样说。在本质上,创建线程只有一种方式,就是构造一个Thread类(其子类其实也可以认为是一个 Thread 类)。
而构造 Thread类 又有两种方式,一种是继承 Thread 类,一种是实现 Runnable接口。其最终都会创建 Thread 类(或其子类)的对象。
再来看实现 Callable ,结合 Future 和 FutureTask 的方式。可以发现,其最终也是通过new Thread(task)
的方式构造 Thread 类。
最后,在线程池中,我们其实是把创建和管理线程的任务都交给了线程池。而创建线程是通过线程工厂类 DefaultThreadFactory 来创建的(也可以自定义工厂类)。我们看下这个工厂类的具体实现。
因此,综上所述。在回答这个问题的时候,我们可以说本质上创建线程就只有一种方式,就是构造一个 Thread 类。
参考
https://cloud.tencent.com/developer/article/1739160