Java 多线程实例详解(二)

Java 多线程实例详解(二)

本文是Java多线程实例系列的第二篇,将进一步介绍Java多线程的实现方式以及相关应用的代码实例。

线程的生命周期

Java线程有5种状态:

  1. 新建状态(New):当线程被创建时,它处于新建状态。
  2. 就绪状态(Runnable):线程获得了CPU资源,并可以执行,但它还未开始执行它的代码。
  3. 运行状态(Running):线程正在执行它的代码。
  4. 阻塞状态(Blocked):线程暂时停止执行,通常是等待某个事件的发生,例如输入输出操作或者等待某个锁的释放。
  5. 终止状态(Terminated):线程已经执行完它的代码或者出现了异常而异常终止。

线程的实现方式

Java实现多线程有两种方式:

方式一:继承Thread类

继承Thread类的方式实现多线程需要重写run()方法,并通过start()方法启动线程。

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("Thread1: " + i);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        thread1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("Main: " + i);
        }
    }
}

方式二:实现Runnable接口

实现Runnable接口的方式实现多线程需要实现run()方法,并通过Thread类的构造方法传入Runnable对象,再通过start()方法启动线程。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("Thread2: " + i);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread2 = new Thread(runnable);
        thread2.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("Main: " + i);
        }
    }
}

线程的常用操作方法

Java提供了一些常用的线程操作方法:

  1. wait()方法:线程在执行wait()方法时会进入阻塞状态,直到其他线程调用notify()方法或notifyAll()方法才能唤醒它。
  2. notify()方法:唤醒处于wait()方法阻塞状态的线程中的一个线程。
  3. notifyAll()方法:唤醒处于wait()方法阻塞状态的所有线程。
  4. sleep()方法:使线程暂停一段时间,单位是毫秒,可避免CPU无限制地独占线程。

示例一:wait()与notify()方法的应用

wait()方法与notify()方法可以协调不同线程的执行,例如下面的示例:

public class ShareData {
    private int count;
    private boolean flag;

    public synchronized void put(int count) {
        if(flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.count = count;
        System.out.println("生产者生产:" + count);
        flag = true;
        notify();
    }

    public synchronized void get() {
        if(!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("消费者消费:" + count);
        flag = false;
        notify();
    }
}

public class Producer implements Runnable {
    private ShareData shareData;

    public Producer(ShareData shareData) {
        this.shareData = shareData;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            shareData.put(i);
        }
    }
}

public class Consumer implements Runnable {
    private ShareData shareData;

    public Consumer(ShareData shareData) {
        this.shareData = shareData;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            shareData.get();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        new Thread(new Producer(shareData)).start();
        new Thread(new Consumer(shareData)).start();
    }
}

以上示例中,生产者线程和消费者线程并不是依次执行,而是在满足条件时交替执行。这是通过wait()方法和notify()方法的配合实现的。

示例二:sleep()方法的应用

一些场景下需要暂停线程一段时间。例如,可以通过调用sleep()方法,模拟一个任务的执行时间,目的是更好地测试并发运行程序的效果。

public class SleepTask implements Runnable {
    private String name;

    public SleepTask(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + " is running.");
        try {
            Thread.sleep(new Random().nextInt(5000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + " is done.");
    }
}

public class Main {
    public static void main(String[] args) {
        String[] tasks = {"task1", "task2", "task3", "task4", "task5"};
        for (String task : tasks) {
            new Thread(new SleepTask(task)).start();
        }
    }
}

sleep()方法的本质是让一个线程暂停执行,让出CPU资源,但不释放锁。假设在一段时间内,只有一个线程处于可执行状态,那么CPU资源将会一直被这个线程所占用,而其他线程只能等待。这时,就需要通过协作式的多线程编程,让当前线程卸载CPU资源,让其他线程能够执行。

结论

通过以上实例说明,在 Java中实现多线程的机制很灵活,有继承Thread类的方式,也有实现Runnable接口的方式,可以通过wait()方法和notify()方法适应不同的场景,利用sleep()方法来模拟线程执行时间。但同时,多线程编程也对线程安全问题提出了更高的要求,需要我们深入理解线程的执行机制及相关问题,进而对多线程程序进行优化。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 多线程实例详解(二) - Python技术站

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

相关文章

  • Java实现数组反转翻转的方法实例

    下面是详细的攻略: 前言 数组反转是一个经典的问题,本文将介绍在Java中实现数组反转的多种方法。 方法一:使用for循环 最容易想到的方法是使用for循环,将数组的前后元素依次交换。 代码实现: int[] arr = {1, 2, 3, 4, 5}; for (int i = 0; i < arr.length / 2; i++) { int te…

    Java 2023年5月26日
    00
  • IDEA配置Maven并版本统一管理的实现

    下面就为大家详细讲解 “IDEA配置Maven并版本统一管理的实现” 的攻略。 1. 配置Maven 1.1 下载安装Maven 首先,在官网下载最新的Maven,并且按照安装提示进行安装。 1.2 配置IDEA 打开IDEA,进行如下的配置: 点击菜单栏的 File -> Settings(或直接使用快捷键 Ctrl + Alt + S )打开设置界…

    Java 2023年5月19日
    00
  • SpringMVC拦截器超详细解读

    以下是关于“SpringMVC拦截器超详细解读”的完整攻略,其中包含两个示例。 SpringMVC拦截器超详细解读 在SpringMVC中,拦截器是一种非常重要的组件,它可以在请求到达控制器方法之前或之后进行一些处理。本攻略将详细介绍SpringMVC拦截器的使用方法和注意事项。 拦截器的作用 拦截器可以在请求到达控制器方法之前或之后进行一些处理,如记录日志…

    Java 2023年5月16日
    00
  • Java Apache POI报错“IllegalStateException”的原因与解决办法

    “IllegalArgumentException”是Java的Apache POI类库中的一个异常,通常由以下原因之一引起: 参数错误:如果参数不正确,则可能会出现此异常。例如,可能会尝试使用错误的参数调用方法。 以下是两个实例: 例1 如果参数不正确,则可以尝试使用正确的参数以解决此问题。例如,在Java中,可以使用以下代码: FileInputStre…

    Java 2023年5月5日
    00
  • Java获得当前时间前指定几个小时具体时间的方法示例

    获取当前时间前几个小时的具体时间,可以用Java中的java.util.Calendar或java.time.LocalDateTime类。 用java.util.Calendar实现 import java.util.Calendar; import java.util.Date; public class GetTimeBeforeHours { pub…

    Java 2023年5月20日
    00
  • Java以编程方式实现JAR文件的创建

    Java以编程方式实现JAR文件的创建,可以通过Java的内置工具jar来实现。以下是完整的攻略: 步骤1:创建Java项目并编写类 首先,需要创建一个Java项目并编写一些类。例如,假设有两个类MyClass和MyUtils。MyClass类提供一些功能,而MyUtils类是一个辅助类,提供了一些可重用的方法。 步骤2:编译Java类并创建jar文件 运行…

    Java 2023年5月20日
    00
  • Spring源码:Bean的生命周期(二)

    前言 让我们继续讲解Spring的Bean实例化过程。在上一节中,我们已经讲解了Spring是如何将Bean定义加入到IoC容器中,并使用合并的Bean定义来包装原始的Bean定义。接下来,我们将继续讲解Spring的 getBean() 方法,特别是针对 FactoryBean 的解析。 在 getBean() 方法中,Spring还支持对 Factory…

    Java 2023年5月1日
    00
  • 深入解析Spring Boot 的SPI机制详情

    深入解析Spring Boot 的SPI机制详情 在Spring Boot中,SPI是一种Java的扩展机制,它让应用程序可以在运行时动态加载一个类或多个类实现的接口,并执行相应的操作。下面我们将深入探究Spring Boot的SPI机制的实现细节。 什么是SPI机制 SPI,全称为Service Provider Interface,是一种Java的扩展机…

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