Java教程中的多线程与程序和示例
任何应用程序都可以有多个进程(实例)。每个进程都可以分配为单个线程或多个线程。我们将在本教程中看到如何同时执行多个任务,并了解有关线程和线程之间同步的更多信息。
在这个 Java 多线程教程中,我们将学习:
- 什么是单线程
- 什么是 Java 中的多线程?
- Java 中的线程生命周期
- Java 线程同步
- Java 多线程示例
什么是单线程?
Java 中的单线程基本上是一个轻量级和最小的处理单元。 Java 通过使用“线程类”来使用线程。
有两种类型的线程——用户线程和守护线程 (当我们要清理应用程序时使用守护线程并在后台使用)。
当应用程序首次启动时,会创建用户线程。贴出来,我们可以创建很多用户线程和守护线程。
单线程示例:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
单线程的优点:
- 在系统中执行单线程时减少应用程序的开销
- 此外,它还降低了应用程序的维护成本。
什么是 Java 中的多线程?
多线程 在 Java 中是同时执行两个或多个线程以最大限度地利用 CPU 的过程。多线程应用程序执行两个或多个并发运行的线程。因此,它在 Java 中也称为并发。每个线程彼此并行运行。多线程不分配单独的内存区域,因此它们节省内存。此外,线程之间的上下文切换需要更少的时间。
多线程示例:
package demotest; public class GuruThread1 implements Runnable { public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
多线程的优点:
- 由于线程是独立的,用户不会被阻塞,我们可以一次执行多个操作
- 由于线程是独立的,如果一个线程遇到异常,其他线程不会受到影响。
Java 中的线程生命周期
线程的生命周期:
<中心>
<图>Java中的线程生命周期
图>
线程生命周期的各个阶段如上图所示:
- 新的
- 可运行
- 跑步
- 等待中
- 死了
- 新功能: 在这个阶段,线程是使用类“线程类”创建的。它保持这个状态直到程序开始 线程。它也被称为天生线程。
- 可运行: 在此页面中,线程的实例是使用 start 方法调用的。将线程控制权交给调度程序以完成执行。这取决于调度程序,是否运行线程。
- 正在运行: 当线程开始执行时,状态变为“运行”状态。调度程序从线程池中选择一个线程,并开始在应用程序中执行。
- 等待: 这是线程必须等待的状态。由于应用程序中有多个线程正在运行,因此需要线程之间的同步。因此,一个线程必须等待,直到另一个线程被执行。因此,这种状态称为等待状态。
- 死亡: 这是线程终止时的状态。线程处于运行状态,一旦完成处理就处于“死状态”。
线程常用的一些方法有:
方法 | 描述 |
---|---|
start() | 这个方法启动线程的执行,JVM调用线程上的run()方法。 |
睡眠(int毫秒) | 此方法使线程休眠,因此线程的执行将暂停提供的毫秒数,之后,线程再次开始执行。这有助于线程同步。 |
getName() | 它返回线程的名称。 |
setPriority(int newpriority) | 改变线程的优先级。 |
产量() | 它会导致当前线程暂停并执行其他线程。 |
示例: 在这个 Java 多线程程序示例中,我们将创建一个线程并探索可用于线程的内置方法。
package demotest; public class thread_example1 implements Runnable { @Override public void run() { } public static void main(String[] args) { Thread guruthread1 = new Thread(); guruthread1.start(); try { guruthread1.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } guruthread1.setPriority(1); int gurupriority = guruthread1.getPriority(); System.out.println(gurupriority); System.out.println("Thread Running"); } }
代码解释:
- 代码行 2: 我们正在创建一个实现 Runnable 接口的类“thread_Example1”(它应该由其实例打算由线程执行的任何类实现。)
- 代码行 4: 它覆盖了可运行接口的 run 方法,因为它必须覆盖该方法
- 代码行 6: 这里我们定义了 main 方法,我们将在其中开始执行线程。
- 代码行 7: 在这里,我们通过实例化一个新的线程类来创建一个名为“guruthread1”的新线程。
- 代码行 8: 我们将使用“guruthread1”实例的线程的“start”方法。线程将在此处开始执行。
- 代码行 10: 这里我们使用“guruthread1”实例的线程的“sleep”方法。因此,线程将休眠 1000 毫秒。
- 代码 9-14: 在这里,我们将 sleep 方法放在 try catch 块中,因为发生了检查异常,即中断异常。
- 代码行 15: 在这里,我们将线程的优先级设置为 1,无论它是哪个优先级
- 代码行 16: 这里我们使用 getPriority() 获取线程的优先级
- 代码行 17: 这里我们打印从 getPriority 获取的值
- 代码行 18: 在这里,我们正在编写线程正在运行的文本。
当你执行上面的代码时,你会得到如下输出:
输出:
5是Thread的优先级,Thread Running是我们代码输出的文本。
Java 线程同步
在多线程中,存在程序的异步行为。如果一个线程正在写入一些数据,而另一个线程同时正在读取数据,可能会在应用程序中造成不一致。
当需要两个或多个线程访问共享资源时,就采用同步的方式。
Java 提供了同步方法来实现同步行为。
在这种方法中,一旦线程到达同步块内部,则没有其他线程可以在同一对象上调用该方法。所有线程都必须等到该线程完成同步块并从中退出。
这样,同步有助于多线程应用程序。一个线程必须等到其他线程执行完毕才允许其他线程执行。
可以写成如下形式:
Synchronized(object) { //Block of statements to be synchronized }
Java 多线程示例
在这个多线程 Java 示例中,我们将采用两个线程并获取线程的名称。
示例 1:
GuruThread1.java package demotest; public class GuruThread1 implements Runnable{ /** * @param args */ public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
代码解释:
- 代码行 3: 我们采用了一个实现 Runnable 的类“GuruThread1”(它应该由其实例打算由线程执行的任何类实现。)
- 代码行 8: 这是类的主要方法
- 代码行 9: 在这里,我们将实例化 Thread 类并创建一个名为“guruThread1”的实例并创建一个线程。
- 代码行 10: 在这里,我们将实例化 Thread 类并创建一个名为“guruThread2”的实例并创建一个线程。
- 代码行 11: 我们正在启动线程,即 guruThread1。
- 代码行 12: 我们正在启动线程,即 guruThread2。
- 代码行 13: 将文本输出为“线程名称如下:”
- 代码行 14: 使用线程类的getName()方法获取线程1的名称。
- 代码行 15: 使用线程类的getName()方法获取线程2的名称。
当你执行上面的代码时,你会得到如下输出:
输出:
线程名称在这里输出为
- 大师1
- 大师2
示例 2:
在这个 Java 中的多线程示例中,我们将学习重写可运行接口的 run() 和 start() 方法,并创建该类的两个线程并相应地运行它们。
另外,我们要上两节课,
- 一个将实现可运行接口和
- 另一个将具有 main 方法并相应地执行。
package demotest; public class GuruThread2 { public static void main(String[] args) { // TODO Auto-generated method stub GuruThread3 threadguru1 = new GuruThread3("guru1"); threadguru1.start(); GuruThread3 threadguru2 = new GuruThread3("guru2"); threadguru2.start(); } } class GuruThread3 implements Runnable { Thread guruthread; private String guruname; GuruThread3(String name) { guruname = name; } @Override public void run() { System.out.println("Thread running" + guruname); for (int i = 0; i < 4; i++) { System.out.println(i); System.out.println(guruname); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread has been interrupted"); } } } public void start() { System.out.println("Thread started"); if (guruthread == null) { guruthread = new Thread(this, guruname); guruthread.start(); } } }
代码解释:
- 代码行 2: 在这里,我们采用了一个“GuruThread2”类,其中包含 main 方法。
- 代码行 4: 这里我们采用了该类的一个 main 方法。
- 代码行 6-7: 在这里,我们创建了一个 GuruThread3 类的实例(在下面的代码行中创建)作为“threadguru1”,我们正在启动线程。
- 代码行 8-9: 在这里,我们将 GuruThread3 类的另一个实例(在下面的代码行中创建)创建为“threadguru2”,并且我们正在启动线程。
- 代码行 11: 在这里,我们创建了一个“GuruThread3”类,它实现了可运行接口(它应该由其实例打算由线程执行的任何类实现。)
- 代码行 13-14: 我们正在获取两个类变量,其中一个是线程类类型,另一个是字符串类。
- 代码行 15-18: 我们重写了 GuruThread3 构造函数,该构造函数将一个参数作为字符串类型(即线程名称),分配给类变量 guruname,从而存储线程的名称。
- 代码行 20: 这里我们重写了可运行接口的 run() 方法。
- 代码行 21: 我们正在使用 println 语句输出线程名称。
- 代码行 22-31: 这里我们使用了一个 for 循环,计数器初始化为 0,它不应小于 4(我们可以取任何数字,因此这里循环将运行 4 次)并递增计数器。我们正在打印线程名称,并在 try-catch 块内使线程休眠 1000 毫秒,因为 sleep 方法引发了检查异常。
- 代码行 33: 这里我们重写了可运行接口的 start 方法。
- 代码行 35: 我们正在输出文本“线程已启动”。
- 代码行 36-40: 这里我们使用一个 if 条件来检查类变量 guruthread 中是否有值。如果它为空,那么我们正在使用线程类创建一个实例,该线程类将名称作为参数(在构造函数中为其分配的值)。之后使用 start() 方法启动线程。
当你执行上面的代码时,你会得到以下输出:
输出 :
因此有两个线程,我们会收到两次消息“线程已启动”。
我们得到线程的名称,因为我们已经输出了它们。
它进入 for 循环,我们打印计数器和线程名称,计数器从 0 开始。
循环执行了 3 次,在这期间线程休眠了 1000 毫秒。
因此,首先,我们得到 guru1,然后是 guru2,然后是 guru2,因为线程在这里休眠 1000 毫秒,然后下一个 guru1 和 guru1,线程休眠 1000 毫秒,所以我们得到 guru2,然后是 guru1。
总结
在本教程中,我们看到了 Java 中的多线程应用程序以及如何在 Java 中使用单线程和多线程。
- 解释Java中的多线程:在多线程中,用户不会被阻塞,因为线程是独立的,并且可以同时执行多个操作
- 线程生命周期的各个阶段是,
- 新的
- 可运行
- 跑步
- 等待中
- 死了
- 我们还了解了线程之间的同步,这有助于应用程序顺利运行。
- Java 中的多线程编程让更多的应用程序任务变得更加容易。
java