更新时间:2022-12-28 13:37:41 来源:极悦 浏览1094次
通常,我们可以将线程定义为一个子进程,它具有最小的进程单元,是轻量级的,并且具有独立的执行路径。这些线程使用共享内存,但它们独立运行,因此即使线程中存在异常也不会影响其他线程的工作,尽管它们共享相同的内存。
正如我们在上图中所观察到的,一个线程在进程内部运行,线程之间将进行基于上下文的切换,操作系统中可以运行多个进程,每个进程又可以同时运行多个线程。多线程概念广泛应用于游戏、动画等领域。
为了帮助用户操作系统为用户提供了多任务处理的特权,用户可以在机器上同时执行多个操作。可以通过两种方式启用此多任务处理:
基于进程的多任务处理
基于线程的多任务处理
在这种类型的多任务处理中,进程是重量级的,每个进程都分配了一个单独的内存区域。并且由于进程是重量级的,进程之间的通信成本很高,进程之间的切换需要很长时间,因为它涉及加载、保存到寄存器、更新映射、列表等操作。
正如我们上面所讨论的,线程具有轻量级的特性,共享相同的地址空间,线程之间的通信成本也很低。
为什么使用线程?
现在,我们可以理解为什么要使用线程,因为它们具有轻量级的优势,并且可以以低成本提供多个线程之间的通信,从而有助于在共享内存环境中进行有效的多任务处理。
线程的生命周期
线程在其生命周期中会进入不同的状态,让我们通过以下几行了解这些状态:在其生命周期中,线程会经历以下状态,即:
新州
活动状态
等待/阻塞状态
定时等待状态
终止状态
我们可以在上图中看到线程中不同状态的工作,让我们详细了解每个状态:
(1)新状态
默认情况下,一个Thread会处于一个new状态,在这个状态下,代码还没有运行,执行过程还没有启动。
(2)活跃状态
默认情况下,处于新状态的 Thread 在调用 start() 方法时会转移到 Active 状态,他的 Active 状态包含两个子状态,即:
可运行状态:在此状态下,线程已准备好在任何给定时间运行,线程调度程序的工作是为可运行状态保留的线程提供线程时间。已获得多线程的程序共享在线程之间共享的时间间隔切片,因此,这些线程运行一段较短的时间跨度,并在可运行状态下等待获取它们的时间间隔调度切片。
Running State:当Thread接收到Thread Scheduler分配的CPU时,从“Runnable”状态转为“Running”状态。在其给定时间片会话期满后,它再次回到“可运行”状态并等待下一个时间片。
(3)等待/阻塞状态
如果线程处于非活动状态但处于临时状态,则它处于等待或阻塞状态,例如,如果有两个线程 T1 和 T2,其中 T1 需要与摄像头通信,而其他线程 T2 已经使用摄像头进行通信扫描然后T1等待直到T2线程完成它的工作,在这个状态下T1停在等待状态,在另一种情况下,用户调用了两个具有相同功能的线程T2和T3,并且都具有线程调度程序给定的相同时间片那么线程 T1、T2 都处于阻塞状态。当有多个线程停在阻塞/等待状态时,线程调度程序通过拒绝不需要的线程并按优先级分配 CPU 来清除队列。
(4)定时等待状态
有时等待线程的较长持续时间会导致饥饿,如果我们举个例子,比如有两个线程 T1,T2 等待 CPU,并且 T1 正在进行关键编码操作,如果它在执行操作之前不退出 CPU,那么 T2 将是暴露在不确定的情况下等待更长时间,为了避免这种饥饿情况,我们有 Timed Waiting 等待状态以避免这种情况,因为在 Timed Waiting 中,每个线程都有一个调用 sleep() 方法的时间段,并且在时间到期,线程开始执行其任务。
(5)终止状态
由于以下原因,线程将处于终止状态:
正常情况下,线程在完成其任务时会终止。
有时,线程可能会由于异常事件(如分段错误、异常等)而终止。这种终止可以称为异常终止。
终止的线程意味着它已经死了并且不再可用。
正如我们所熟悉的,我们在每个 Java 程序中创建 Main 方法,它作为代码由 JVM 执行的入口点,同样在这个多线程概念中,每个程序都有一个主线程,默认情况下由JVM,因此无论何时在 Java 中创建程序,JVM 都会为其执行提供主线程。
我们可以使用两种方式在 java 中创建线程,即:
通过扩展线程类
通过实现 Runnable 接口
通过扩展Thread类
我们可以使用 Thread 类在 Java 中运行线程,Thread 类提供构造函数和方法来创建线程并在线程上执行操作,线程扩展了可以实现 Runnable 接口的 Thread 类。我们使用以下构造函数来创建线程:
线
线程(可运行 r)
线程(字符串名称)
Thread(Runnable r, String name)
通过扩展线程类创建线程的示例代码:
import java.io.*;
import java.util.*;
public class GFG extends Thread {
// initiated run method for Thread
public void run()
{
System.out.println("Thread Started Running...");
}
public static void main(String[] args)
{
GFG g1 = new GFG();
// invoking Thread
g1.run();
}
}
输出
线程开始运行...
使用 Runnable 接口创建线程的示例代码:
import java.io.*;
import java.util.*;
public class GFG implements Runnable {
// method to start Thread
public void run()
{
System.out.println(
"Thread is Running Successfully");
}
public static void main(String[] args)
{
GFG g1 = new GFG();
// initializing Thread Object
Thread t1 = new Thread(g1);
t1.run();
}
}
输出
线程运行成功
使用 Thread(String name) 在 Java 中创建线程的示例代码:
import java.io.*;
import java.util.*;
public class GFG {
public static void main(String args[])
{
// Thread object created
// and initiated with data
Thread t = new Thread("Hello!");
// Thread gets started
t.start();
// getting data of
// Thread through String
String s = t.getName();
System.out.println(s);
}
}
输出
你好!
使用 Thread(Runnable r, String name) 创建线程对象的示例 Java 代码:
import java.io.*;
import java.util.*;
public class GFG implements Runnable {
public void run()
{
System.out.println(
"Thread is created and running successfully...");
}
public static void main(String[] args)
{
// aligning GFG Class with
// Runnable interface
Runnable r1 = new GFG();
Thread t1 = new Thread(r1, "My Thread");
// Thread object started
t1.run();
// getting the Thread
// with String Method
String str = t1.getName();
System.out.println(str);
}
}
输出
线程已创建并成功运行...
我的线程
探索不同线程状态的 Java 程序:
让我们通过在线程 t1 和 t2 上实现它们来了解线程状态的工作原理。
输出:
import java.io.*;
import java.util.*;
class GFG implements Runnable {
public void run()
{
// implementing try-catch Block to set sleep state
// for inactive thread
try {
Thread.sleep(102);
}
catch (InterruptedException i1) {
i1.printStackTrace();
}
System.out.println(
"The state for t1 after it invoked join method() on thread t2"
+ " " + ThreadState.t1.getState());
// implementing try-catch block
try {
Thread.sleep(202);
}
catch (InterruptedException i2) {
i2.printStackTrace();
}
}
}
// creation of ThreadState class
// to implement Runnable interface
public class ThreadState implements Runnable {
public static Thread t1;
public static ThreadState o1;
public static void main(String args[])
{
o1 = new ThreadState();
t1 = new Thread(o1);
System.out.println("post-spanning, state of t1 is"
+ " " + t1.getState());
// lets invoke start() method on t1
t1.start();
// Now,Thread t1 is moved to runnable state
System.out.println(
"post invoking of start() method, state of t1 is"
+ " " + t1.getState());
}
public void run()
{
GFG g1 = new GFG();
Thread t2 = new Thread(g1);
// Thread is created and its in new state.
t2.start();
// Now t2 is moved to runnable state
System.out.println(
"state of t2 Thread, post-calling of start() method is"
+ " " + t2.getState());
// create a try-catch block to set t1 in waiting
// state
try {
Thread.sleep(202);
}
catch (InterruptedException i2) {
i2.printStackTrace();
}
System.out.println(
"State of Thread t2 after invoking to method sleep() is"
+ " " + t2.getState());
try {
t2.join();
System.out.println(
"State of Thread t2 after join() is"
+ " " + t2.getState());
}
catch (InterruptedException i3) {
i3.printStackTrace();
}
System.out.println(
"state of Thread t1 after completing the execution is"
+ " " + t1.getState());
}
}
输出
后跨越,t1 的状态是新的
调用 start() 方法后,t1 的状态为 RUNNABLE
t2 线程的状态,调用 start() 方法后为 RUNNABLE
t1 在线程 t2 上调用 join method() 后的状态 TIMED_WAITING
调用方法 sleep() 后线程 t2 的状态为 TIMED_WAITING
join() 终止后线程 t2 的状态
执行完成后线程 t1 的状态为 RUNNABLE
以上就是关于“Java线程详解”的介绍,大家如果想了解更多相关知识,不妨来关注一下本站的Java极悦在线学习,里面的课程内容细致全面,很适合没有基础的小伙伴学习,希望对大家能够有所帮助。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习