📜  Java线程

📅  最后修改于: 2022-05-13 01:55:06.485000             🧑  作者: Mango

Java线程

通常,我们可以将线程定义为具有最小进程单元的轻量级子进程,并且还具有单独的执行路径。这些线程使用共享内存,但它们独立运行,因此如果线程中存在不影响其他线程工作的异常,尽管它们共享相同的内存。

操作系统中共享内存环境中的线程

操作系统中共享内存环境中的线程

正如我们在上图中所看到的,上图中一个线程在进程内部运行,并且在线程之间会有基于上下文的切换,操作系统中可以运行多个进程,并且每个进程又可以有多个线程同时运行。多线程概念广泛应用于游戏、动画……等。

多任务处理的概念

为了帮助用户操作系统为用户提供了多任务处理的特权,用户可以在机器上同时执行多个操作。这种多任务可以通过两种方式启用:

  1. 基于过程的多任务处理
  2. 基于线程的多任务处理

1. 基于进程的多任务(Multiprocessing)

在这种类型的多任务中,进程是重量级的,每个进程都由一个单独的内存区域分配。由于进程是重量级的,进程之间的通信成本很高,并且进程之间的切换需要很长时间,因为它涉及加载、保存在寄存器中、更新映射、列表等操作。

2. 基于线程的多任务处理

正如我们上面讨论的,线程具有轻量级的特性,共享相同的地址空间,线程之间的通信成本也很低。

为什么使用线程?

现在,我们可以理解为什么要使用线程,因为它们具有轻量级的优势,并且可以以低成本提供多个线程之间的通信,有助于在共享内存环境中进行有效的多任务处理。

线程的生命周期

线程在其生命周期中会进入不同的状态,让我们在以下几行中了解这些状态:在其生命周期中,线程经历以下状态,即:

  1. 新州
  2. 活动状态
  3. 等待/阻塞状态
  4. 定时等待状态
  5. 终止状态

线程的生命周期

我们可以在上图中看到一个线程中不同状态的工作,让我们详细了解每个状态:

1.新状态

默认情况下,一个线程将是一个新的状态,在这个状态下,代码还没有运行,执行过程还没有启动。

2.活动状态

默认情况下为新状态的线程在调用 start() 方法时会转移到 Active 状态,其 Active 状态包含两个子状态,即:

  • 可运行状态:在此状态下,线程已准备好在任何给定时间运行,线程调度程序的工作是为可运行状态保留的线程提供线程时间。获得多线程的程序共享线程之间共享的时间间隔切片,因此,这些线程运行一段时间并在可运行状态下等待以获取时间间隔的调度切片。
  • 运行状态:当线程接收到线程调度器分配的CPU时,它从“可运行”状态转移到“运行”状态。并且在其给定的时间片会话到期后,它再次回到“可运行”状态并等待下一个时间片。

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 Method,它作为代码被 JVM 执行的入口点,类似地在这个多线程概念中,每个程序都有一个 Main Thread,这是由默认提供的JVM,因此每当在Java中创建程序时,JVM 都会为其执行提供主线程。

如何使用Java编程语言创建线程?

我们可以使用两种方式在Java中创建线程,即:

  1. 通过扩展线程类
  2. 通过实现 Runnable 接口

1.通过扩展线程类

我们可以通过使用 Thread 类在Java中运行线程,它提供了用于在 Thread 上创建和执行操作的构造函数和方法,它扩展了可以实现 Runnable 接口的 Thread 类。我们使用以下构造函数来创建线程:

  • 线
  • 线程(可运行 r)
  • 线程(字符串名称)
  • 线程(字符串名称,可运行 r)

通过扩展线程类创建线程的示例代码:

Java
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.start();
    }
}


Java
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.start();
    }
}


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 Geeks!");
 
        // Thread gets started
        t.start();
 
        // getting data of
          // Thread through String
        String s = t.getName();
        System.out.println(s);
    }
}


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.start();
        // getting the Thread
          // with String Method
        String str = t1.getName();
        System.out.println(str);
    }
}


Java
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();
        }
        catch (InterruptedException i3) {
            i3.printStackTrace();
        }
        System.out.println(
            "state of Thread t2 after completing the execution is"
            + " " + t1.getState());
    }
}



输出
Thread Started Running...

使用 Runnable 接口创建线程的示例代码:

Java

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.start();
    }
}


输出
Thread is Running Successfully

使用 Thread(String name) 在Java中创建 Thread 的示例代码:

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 Geeks!");
 
        // Thread gets started
        t.start();
 
        // getting data of
          // Thread through String
        String s = t.getName();
        System.out.println(s);
    }
}


输出
Hello Geeks!

使用 Thread(Runnable r, String name) 创建 Thread 对象的示例Java代码:

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.start();
        // getting the Thread
          // with String Method
        String str = t1.getName();
        System.out.println(str);
    }
}


输出
My Thread
Thread is created and running successfully...

探索不同线程状态的Java程序:

让我们通过在线程 t1 和 t2 上实现它们来查看线程状态的工作。

Java

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();
        }
        catch (InterruptedException i3) {
            i3.printStackTrace();
        }
        System.out.println(
            "state of Thread t2 after completing the execution is"
            + " " + t1.getState());
    }
}

输出

post-spanning, state of t1 is NEW
post invoking of start() method, state of t1 is RUNNABLE
state of t2 Thread, post-calling of start() method is RUNNABLE
The state for t1 after it invoked join method() on thread t2 TIMED_WAITING
State of Thread t2 after invoking to method sleep() is TIMED_WAITING
state of Thread t2 after completing the execution is RUNNABLE