创建线程的几种方式
方法 | 解释 |
---|---|
Thread() | 创建线程对象 |
Thread(String name) | 创建线程对象,并给线程命名,不会影响线程 |
Thread(Runnable runnable) | 使用Runnable对象创建线程 |
Thread(Runnable runnable, String name) | 使用Runnable对象创建线程并给线程命名 |
方式1.创建一个类,继承Thread
每一个线程都是一个单独的”执行流“, 都可以执行一段代码逻辑,但是,线程是从哪里开始执行呢???就需要提供一个入口,而run方法就是线程的入口,表示就从run方法这里开始执行;
此时,我们写的一个Java程序其实就是一个进程,一个进程里面至少要有一个线程,就是主线程,而在Java程序中,主线程的入口方法就是main方法;
//创建一个类,继承Thread
class MyThread extends Thread{
//重写Thread里面的run方法,这个方法就是线程的入口
@Override
public void run() {
//代码逻辑
}
}
public class Demo1 {
public static void main(String[] args) {
}
}
但是,只有run方法还是不够的,run方法只是线程执行的入口,只是说明了线程从哪个地方开始执行,run方法里面只是定义了线程要做哪些任务,需要在主线程中,调用 start() 方法来创建一个新的线程,线程创建后,线程就会调用run()方法开始执行任务。
代码如下:
//创建一个类,继承Thread
class MyThread extends Thread{
//重写Thread里面的run方法,这个方法就是线程的入口
@Override
public void run() {
System.out.println("线程正在工作");
}
}
public class Demo1 {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
//run() 和 start() 都是Thread的方法
//run()方法只是线程的入口
//start()方法才是调用了系统API来创建一个线程,让线程再调用run来执行任务
}
}
下面演示一下两个线程并发执行的情况:
class MyThread extends Thread{
//重写Thread里面的run方法,这个方法就是线程的入口
@Override
public void run() {
//写一个while循环让这个线程一直打印
while(true) {
System.out.println("hello Thread");
try {
//进行一个休眠方便观察
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
//写一个while循环,一直打印
while(true) {
System.out.println("hello main");
//进行一个休眠方便观察
Thread.sleep(1000);
}
}
}
上述结果就可以看到,两个线程分别在执行自己的代码,这也就印证了每一个线程都是一个单独的”执行流“, 本来在运行时只有一个执行流,但是遇见 thread.start() ,就开始了兵分两路”同时执行“, 就达到了并发编程的效果,而这里的并发指的是”并行+并发“, 因为,程序员在写代码的时候,是无法感知到这两个线程到底是在一个CPU核心上调度执行还是在两个CPU核心上同时执行, 所以在宏观上也就是我们人的肉眼看着都是在同时执行的,这一点在进程那篇文章中已经讲解的很清楚了。
如果将代码中的 thread.start() 改为 thread.run() 会发生什么呢?
如果改成thread.run(), 它就只剩下一个主线程了,只会按照代码的顺序依次执行,就变成了单独的方法调用,这就不是多线程了,只有当run()方法结束后,才会继续向下执行;也就没有实现”并发编程”;
方式2.创建一个类,实现Runnable接口
使用Runnable接口和继承Thread的区别就是为了解耦合,Runnable 就相当于是一个任务,在Runnable 中,也实现了 run() 方法,所以,就可以在Runnable 中写逻辑代码,然后,将这个Runnable 任务交给线程来执行。
代码如下:
//创建一个类,实现Runnable接口
class MyThread2 implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("hello Thread");
}
}
}
public class Demo2 {
public static void main(String[] args) {
//Runnable 就表示的是这是一个可执行的任务
Runnable runnable = new MyThread();
Thread thread = new Thread(runnable);
thread.start();
while(true) {
System.out.println("hello main");
}
}
}
方式3.继承Thread,重写run(), 但是使用匿名内部类
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("hello Thread");
}
};
thread.start();
System.out.println("hello main");
}
方法4.实现Runnable,重写run(), 但是使用匿名内部类
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("hello Thread");
}
};
Thread thread = new Thread(runnable);
thread.start();
System.out.println("hello main");
}
方式5.使用Lambda表达式
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("hello Thread");
});
thread.start();
System.out.println("hello main");
}
注意:上述这几种创建线程的方式只是一部分并非全部,创建线程有许多种方式,这几种比较简单而已,在多线程进阶中,还会再介绍几种创建线程的方式。