系列文章目录
🌈 座右铭🌈:人的一生这么长、你凭什么用短短的几年去衡量自己的一生!
💕个人主页: 清灵白羽 漾情天殇_计算机底层原理,深度解析C++,自顶向下看Java-CSDN博客
❤️相关文章 ❤️:清灵白羽 漾情天殇-CSDN博客
目录
前言
今天的这篇文章主要为大家介绍一下Java当中的线程是如何创建的,这里为大家分别介绍了几种方式,内容比较简单,但是涉及到了之前JavaSE的一些语法细节,如果有遗忘的话大家可以翻阅我之前的文章,能够帮助到各位就是对我最大的鼓励!
一、继承Thread类
首先我提示一下这里使用到了多态的语法概念如果对于这方面内容有不了解的话可以先去复习一下多态的概念,或者看我之前介绍过有关多态的文章。
1、创建自定义线程类
首先我们需要创建一个自定义的线程类,该类继承自Thread类,并且重写了其中的run()方法,以定义线程的执行逻辑。
javapackage Yangon; class MyThread extends Thread{ @Override public void run() { System.out.println("线程执行!"); } } public class Main { }
2、创建线程对象并且启动
创建自定义的线程类的对象,并且调用其start()方法,以启动线程。
javapublic class Main { public static void main(String[] args) { Thread thread = new MyThread(); thread.start(); } }
这里就使用到了向上转型,使用多态。
3、线程生命周期
当调用线程对象的start()方法时,线程进入就绪状态,等待CPU的调度执行,一旦CPU调度到该线程的时候就会执行其中的run()方法,当run()方法执行完毕或者线程被中断的时候线程就会结束等待下一次调用或者直接销毁。
我在这里多说一句,线程的创建并不一定要使用多态,也可以直接使用Thread来创建新的线程,直接给Thread传递一个Runnable(这个东西我一会会讲)即可。
javapublic class Main { public static void main(String[] args) { Runnable myRunnable = () -> { // 在这里定义线程的执行逻辑 System.out.println("MyThread is running..."); }; Thread myThread = new Thread(myRunnable); myThread.start(); } }
拓展:start()和run()的区别
在Java当中,线程的启动涉及到两个重要的方法,run方法和start方法,他们之间却有着很大的区别:
1、run()方法
只是Thread的一个普通的方法用以定义线程的执行逻辑,当我们直接调用一个线程对象的run方法的时候并不会线程新的线程,而是在当前线程当中执行run方法的代码。如果我们通过继承Thread类并且重写其run方法来创建新的线程时,当我们调用该线程的run方法实际上只是在当前线程中执行了自己定义的新线程的run方法,并没有新的线程产生,程序还是只有一个执行流。
2、start()方法
start()方法是一个用于启动一个新线程的重要方法,当我们调用一个线程对象的start方法的时候,系统会为该线程创建一个新的线程,并且在新线程当中调用run方法,同样的使用继承Thread类来创建新线程的方法时,我们调用start方法,系统产生一个新线程并且在新线程当中执行run方法,这个时候系统有两个执行流。这就是他们之间的区别。
二、实现Runnable接口
1、实现Runnable接口
1、创建线程任务类
首先,我们需要创建一个类,实现Runnable接口,并且重写其中的run()方法,定义线程当中的执行逻辑。
javaclass MyTask implements Runnable{ @Override public void run() { System.out.println("线程执行"); } }
2、创建线程对象并且传入线程任务
接下来我们需要创建一个Thread类的对象,并且将实现了Runnable接口的线程任务对象作为参数传递给Thread的构造方法。
javapublic class Main { public static void main(String[] args) { Thread thread = new Thread(new MyTask()); thread.start(); } }
3、启动线程
最后我们只需要调用start()方法启动线程即可。通过实现Runnable接口来创建新线程的优势在于能够更好地支持面向对象的设计原则,并且提供了更好的线程任务与线程类的解耦,此外通过实现Runnable接口,多个线程可以共享同一个线程任务对象,避免了多重继承带来的局限性,因此我们推荐使用Runnable接口的方法创建新线程。
2、以上两种方式的区别
继承Thread类,直接使用this引用表示当前线程对象的引用,如果是实现Runnable接口,this表示的是MyTask的引用,需要使用Thread.currentThread()解释一下。
1、Runnable当中的this引用
在Java当中通过实现Runnable接口创建线程的时候,this引用关键字代表实现了Runnable接口的类的实例的引用(这句话有点拗口),而不是线程对象本身,因此我们在实现了Runnable接口的类当中使用this它将引用到该类的实例,而不是代表正在执行的线程对象。
但是在某种情况下我们可能需要获取当前正在执行的线程对象的引用,例如在多线程环境下,你想要获取当前线程的一些属性或者执行某些操作,这个时候就需要使用Thread类的静态方法currentThread()来获取当前线程的引用。
javaclass MyRunnable implements Runnable{ @Override public void run() { Thread thread = Thread.currentThread(); System.out.println("当前线程的名称:" + Thread.currentThread().getName()); System.out.println("当前线程的优先级:" + thread.getPriority()); //Thread.currentThread().getName() 两种方式等价 } } public class Main { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); } }
在上面的例子中,通过调用Thread.currentThread()方法,我们获取了当前正在执行的线程对象的引用,并通过该引用调用了Thread类的一些方法,如getName()和getPriority()来获取线程的名称和优先级。这样就能够在Runnable接口实现类中获取到当前线程对象的引用,并对其进行操作。
2、Thread继承类当中的this引用
当我们继承Thread类来创建线程的时候,在线程的运行过程当中,this关键字确实代表线程对象的引用,也就是说this指向了正在执行该线程的Thread对象。
javaclass MyThread extends Thread{ @Override public void run() { System.out.println("当前线程名称:" + this.getName()); System.out.println("当前线程优先级:" + this.getPriority()); System.out.println("MyThread is running"); } } public class Main { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
在这个例子中,当你调用myThread.start()时,系统会创建一个新的线程,并调用MyThread类的run()方法。在run()方法中,this关键字代表了当前线程对象,我们可以通过this来访问当前线程的属性和方法,比如getName()和getPriority()来获取当前线程的名称和优先级。
三、匿名内部类创建线程
1、匿名内部类创建Thread对象
javapublic class Main { public static void main(String[] args) { Thread thread = new Thread(){ @Override public void run() { System.out.println("MyThread is running"); } }; thread.start(); } }
在这个例子当中,我们创建了一个Thread的匿名子类,并且重写了其run()方法,然后直接在main方法当中创建了这个Thread子类的对象,然后调用其start()方法启动线程,这种方式可以省略编写一个具体的Thread子类的步骤,使得代码更加简洁。
2、匿名内部类创建Runnable子类对象
javapublic class Main { public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Runnable is running"); } }; Thread thread = new Thread(runnable); thread.start(); } }
在这个例子中,我们创建了一个实现了Runnable接口的匿名内部类,并重写了其run()方法。然后,我们将这个匿名内部类的对象传递给了Thread类的构造方法,从而创建了一个新的线程对象。最后调用start()方法启动了线程。