线程的创建
一.继承Thread类
1一个程序正在运行的时候最少有一个进程,比如我们经常见到的public static void main(),他是由jvm去创建的。
进程具有并发执行的特点,线程是进程的“轻量级”表现。也就是说不同的线程也可以同时执行。所以在一个程序中不单单只能有一个线程去执行代码,也可以有多个线程同时去执行。多线程编程可以提高程序的并发性,提高资源的利用率,适应复杂的业务逻辑等优点。所以掌握多线程编程是很重要的。java给我们提供了实现多线程的方式,继承Thread类或实现Runnable接口。
二.Thread类
点开源码查看Thread类,发现Thread实现了Runnable接口。
继续点过去查看,Runnable里面有个抽象的run方法,所以只要是实现了Runnable接口的类必然要重写run方法。
Thread类确实重写了run方法。
那么如何使用Thread类和Runnable接口执行多线程编程呢?
class MyThread1 extends Thread{
public void run(){
while(true) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Test4 {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
myThread1.start();//启动线程
while(true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
让我们自己的类继承Thread类并且重写run方法,run方法里面写我们自己的需要执行的逻辑,并通过start方法启动线程。从运行结果上来看,2个线程并不是有规律的打印,这是因为,操作系统调用正在执行同时执行线程是随机的概率不等的。
通过jconsole我们发现这2个线程确实在运行,说明线程创建成功。
class MyThread1 extends Thread{
public void run(){
while(true) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Test4 {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
myThread1.run();
while(true){
System.out.println("执行main线程了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
当我们把start方法改为run方法,发现并没有执行线程run方法之后的代码。这是因为run方法并没有真正的创建线程。
继续查看console,确实只有一个main线程,run并没有创建线程。
总结:run方法是runnable接口中的一个抽象方法。Thread方法实现了runnable接口,重写了run方法。当调用run方法时候,线程并未创建,相当于main函数去调用普通方法,去执行run方法的内容。当调用start方法时,会调用操作系统的Api接口,在操作系统内核去创建出对应的pcb进程块,并加入到对应的链表中去。使用run方法无法进行多线程编程,通过start方法进行多线程。start方法会为线程进行资源分配,run方法只是普通方法调用。
三.实现Runnable接口
class Runnable1 implements Runnable{
@Override
public void run() {
while(true){
System.out.println("hello thread");
}
}
}
public class Test4 {
public static void main(String[] args) {
Runnable1 runnable1 = new Runnable1();
Thread thread = new Thread();
thread.start();
}
}
Runable接口被实例化后当做Thread的参数给传过去,让Runnable和Thread搭配使用。把要执行的东西放到Runnable里面,Thread去执行Runnable里面的东西。这样做的好处是可以让程序更加灵活,以后代码中想让进程或者携程去执行,只需要把Runnable放到进程或者携程里面就行,使代码更加灵活。
四.匿名内部内
public class Test4 {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
super.run();
while (true) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
thread.start();
}
}
总结:
1.简洁性:无需单独创建一个类来定义线程,使代码更加简洁。
2.封装性:线程的执行逻辑被封装在匿名内部类中,提高了代码的可读性和可维护性。
3.灵活性:可以在需要的地方直接定义和启动线程,方便根据具体需求进行定制。
五.使用lambda表达式创建线程
public class Test4 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
}
}