Java中Thread类详解及常用的方法

Java中Thread类详解及常用的方法

在Java中,Thread类是用来实现多线程编程的核心类。每个Java应用程序都至少有一个线程,这个线程是由JVM(Java 虚拟机)创建的,并且负责程序的主方法的执行。不仅如此,除了主线程,Java应用程序可以有其他线程,这些线程可以是由主线程或其他线程创建的,Java 中的 Thread 类就是用于实现这些线程的。

创建并启动一个线程

创建Thread对象的第一种方法是实现Runnable接口。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable is running.");
    }
}

public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

以上代码展示了第一种方法的实现。可以看到,我们首先定义了一个实现了Runnable接口的类 MyRunnable。在这个类中,我们实现了run()方法,并在其中写下了我们想让线程执行的代码。接着,我们创建了一个 MyRunnable的实例,并将其作为参数传递给Thread类的构造函数。最后,我们调用 start()方法开始执行该线程。

创建Thread对象的第二种方法是继承Thread类。

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread is running.");
    }
}

public class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

从以上代码中,我们可以看到,MyThread类继承了 Thread类,并实现了run()方法。在主方法中,我们创建了一个 MyThread的实例,并直接调用它的start()方法开始执行该线程。

线程方法

start()

start()方法用来启动线程,调用该方法使得线程进入就绪状态。当线程获得 CPU 时间片后,就开始执行 run()方法。

join()

当一个线程调用另一个线程的join()方法时,调用线程将被阻塞,直到被调用线程执行完为止。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable is running.");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyRunnable is finished.");
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        System.out.println("Main thread is running.");
        thread.join();
        System.out.println("Main thread is finished.");
    }
}

以上代码中, join()方法被调用后,主线程将被阻塞,直到线程 thread 执行完后,主线程才会继续执行。

yield()

在一个多线程应用中,线程运行时常常需要等待某个事件的发生,但并不能确定该事件究竟要等多少时间。在这种情况下,可以使用 yield()方法来使得线程放弃当前的 CPU 时间片,让其它线程运行。

class MyRunnable1 implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable1 is running.");
        Thread.yield();
        System.out.println("MyRunnable1 is finished.");
    }
}

class MyRunnable2 implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable2 is running.");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyRunnable2 is finished.");
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable1 myRunnable1 = new MyRunnable1();
        MyRunnable2 myRunnable2 = new MyRunnable2();
        Thread thread1 = new Thread(myRunnable1);
        Thread thread2 = new Thread(myRunnable2);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("Main thread is finished.");
    }
}

MyRunnable1线程执行到 yield()方法时,其它线程将有机会获得 CPU 时间片。

sleep()

sleep()方法让当前正在执行的线程休眠指定的时间,在这段时间内,线程暂时释放CPU控制权,其他线程得以运行。sleep()方法会抛出一个异常InterruptedException,所以在使用sleep()方法时通常要捕获这个异常。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable is running.");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyRunnable is finished.");
    }
}

public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

以上代码中, MyRunnable线程在执行到Thread.sleep(2000)方法时将会休眠2秒钟。

线程状态

一个线程在它的生命周期中可能处于以下五个状态的任意一个状态。

  1. 新建状态(New):刚刚创建一个线程对象时,它处于新建状态
  2. 就绪状态(Runnable):当调用start()方法后,线程进入就绪状态
  3. 运行状态(Running):当就绪状态的线程被调度并获得CPU执行时间,它就进入运行状态
  4. 阻塞状态(Blocked)或等待状态(Waiting)或计时等待状态(Time Waiting):当线程执行一个同步方法时,线程因为不能获取到所需的锁而进入阻塞状态;线程调用了wait()方法,进入等待状态;线程调用了sleep()方法或调用了带有超时参数的方法,进入计时等待状态。
  5. 终止状态(Terminated):当线程执行完毕或者发生了一个未捕获的异常并被有效地处理后,线程处于终止状态。

示例说明

以下示例将创建两个线程,并展示它们的不同状态。

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread is running.");
        System.out.println("MyThread state is " + this.getState().toString());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread is finished.");
        System.out.println("MyThread state is " + this.getState().toString());
    }
}

public class Test {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        System.out.println("Thread1 state is " + myThread1.getState().toString());
        System.out.println("Thread2 state is " + myThread2.getState().toString());
        myThread1.start();
        myThread2.start();
        System.out.println("Thread1 state is " + myThread1.getState().toString());
        System.out.println("Thread2 state is " + myThread2.getState().toString());
    }
}

以上代码中,我们创建了两个 MyThread线程,并在主方法中获取了它们的状态。然后,我们启动了这两个线程,并再次获取它们的状态。最终,我们顺序等待这两个线程执行完成后,再次获取它们的状态。

输出:

Thread1 state is NEW
Thread2 state is NEW
MyThread is running.
Thread1 state is RUNNABLE
Thread2 state is RUNNABLE
MyThread is running.
MyThread state is RUNNABLE
Thread1 state is TIMED_WAITING
Thread2 state is RUNNABLE
MyThread is finished.
MyThread state is TERMINATED
Thread1 state is TERMINATED
Thread2 state is TIMED_WAITING
MyThread is finished.
MyThread state is TERMINATED
Thread2 state is TERMINATED

可以看到,线程在被创建后,初始状态为 NEW;在调用了 start()方法后,状态变为了 RUNNABLE。在一个线程正在执行时,状态为 RUNNING;在一个线程正在等待获取一个锁的时候,状态为 BLOCKED。而当一个线程执行 wait()方法时,线程会进入等待状态,状态为 WAITING;当线程调用 sleep()方法或带有超时参数的方法时,进入计时等待状态,状态为 TIMED_WAITING。对于已经完成工作的线程,其状态为 TERMINATED

另外,需要注意的是,getState()方法不是同步的。如果它被调用时线程正在运行,并且线程的状态正在变化,那么可能会无法获取到准确的状态。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中Thread类详解及常用的方法 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • Java Mybatis数据源之工厂模式

    Java Mybatis数据源之工厂模式 概述 在Java Mybatis中使用工厂模式可以有效地避免配置数据源时的硬编码及大量的重复代码,提高了代码的可维护性和可读性。 工厂模式的实现 工厂模式中通常有三个抽象角色,分别是工厂接口、具体工厂和产品接口。 在Java Mybatis中,可以将DataSource抽象为产品接口,将DataSourceProvi…

    Java 2023年5月20日
    00
  • Java实现文件分割与合并

    当我们处理大量数据时,文件分割与合并是一项非常重要的技能。对于Java开发者来说,使用Java实现文件分割与合并是一项基本技能。下面是一些示例,解释如何使用Java实现这些操作。 1. 文件分割 对大型文件进行分割是一种常见的文件处理方式。Java提供了许多方法来实现此目的。以下代码显示了如何使用Java分割文件: import java.io.*; pub…

    Java 2023年5月20日
    00
  • 详解android studio游戏摇杆开发教程,仿王者荣耀摇杆

    Android Studio游戏摇杆开发教程 本教程将介绍如何在Android Studio中开发游戏摇杆控件,以实现类似于王者荣耀游戏的摇杆控制功能。本教程将涉及到如下内容: 摇杆的原理及实现技术; 摇杆控件的设计; 使用摇杆控件实现王者荣耀摇杆控制功能。 摇杆原理及实现技术 摇杆控件常用的实现方式是利用手指在摇杆区域内滑动的距离和方向来实现控制操作。我们…

    Java 2023年5月26日
    00
  • Java线程池高频面试题总结

    Java线程池高频面试题总结 线程池是什么 线程池是一种用于管理多个线程的机制,它能够根据应用程序需要动态地增减线程。线程池在执行完任务后并不会立即销毁线程,而是将线程放入池中等待下一次使用。线程池通常会预先准备好一定数量的线程,这些线程被称为核心线程,在需要时更多的线程将被创建。 为什么使用线程池 线程池有以下优点: 减少线程创建的开销: 创建线程需要花费…

    Java 2023年5月19日
    00
  • Spring 异步接口返回结果的四种方式

    下面详细讲解Spring异步接口返回结果的四种方式。 1. 使用Callable Spring提供了一个非常简洁的方式来处理异步请求,即使用Java 5中引入的Callable接口。可以使用返回Callable的Controller方法来处理异步请求,Spring会将Callable提交到任务执行器中执行,然后将结果写入响应体中。 示例代码: @RestCo…

    Java 2023年5月31日
    00
  • 吃透Redis面试八股文

    Redis连环40问,绝对够全! Redis是什么? Redis(Remote Dictionary Server)是一个使用 C 语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis 的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。…

    2023年4月24日
    00
  • 五分钟解锁springboot admin监控新技巧

    五分钟解锁 Spring Boot Admin 监控新技巧 Spring Boot Admin 是一个用于监控和管理 Spring Boot 应用程序的开源项目。本文将介绍如何在 5 分钟内轻松启用和配置 Spring Boot Admin 监控。 步骤一:添加 Spring Boot Admin 依赖项 首先,需要添加以下 Spring Boot Admi…

    Java 2023年5月20日
    00
  • SpringMvc后台接收json数据中文乱码问题详解

    下面我将详细讲解关于 SpringMvc 后台接收 JSON 数据中文乱码问题的解决方案。 问题描述 当我们使用 SpringMvc 后台接收 JSON 数据时,常常会出现中文乱码的问题。具体表现为前端使用 axios 或 jQuery.ajax 等发送中文数据时,后台接收到的数据变成了一串乱码,而且无法正常处理和显示。 原因分析 造成这个问题的原因是因为客…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部