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 3种方法实现进制转换

    Java 3种方法实现进制转换是一个很基础的知识点,需要掌握的细节较多。在进行进制转换时,需要将目标进制的数位按权展开,并乘以相应的权值,再将结果相加即可。Java 语言提供了多种方法来实现进制转换,下面分别进行详细讲解: 1. 常规方法 常规方法是最直接的一种进制转换方法,使用起来简单明了。Java 提供了 Integer 类中的 toBinaryStri…

    Java 2023年5月26日
    00
  • Maven修改运行环境配置代码实例

    下面是 Maven 修改运行环境配置代码实例的完整攻略。 什么是 Maven Maven 是一款 Java 项目管理工具,可以帮助我们自动管理 Java 项目中的依赖、编译、测试、打包等工作。在 Maven 中,所有的项目都是通过一个个 POM(Project Object Model) 文件来描述的。 如何修改运行环境配置 Maven 的运行环境配置主要指…

    Java 2023年5月20日
    00
  • Java Mybatis框架由浅入深全解析上篇

    Java Mybatis框架由浅入深全解析上篇 介绍 Java Mybatis框架是一个基于Java语言的数据映射框架,它是一种半自动化的ORM框架,通过XML配置文件或注解的方式将Java对象与数据库进行映射。 Mybatis的基本结构 Mybatis的基本结构包括四个部分: Configuration(配置类):读取mybatis配置文件中的信息,生成全…

    Java 2023年5月19日
    00
  • java实现日历窗口小程序

    Java实现日历窗口小程序攻略 1. 实现思路 要实现一个日历窗口小程序,可以考虑以下几个步骤: 创建一个Swing界面,显示当前日期以及日历窗口。 在日历窗口中显示当前月份的日历。 提供按钮或其他交互方式,让用户可以切换月份,也可以选择某一天进行其他操作。 2. 示例1:显示当前月份的日历 下面是一个简单的实现示例,可以通过一个二维数组表示一个月份的日历:…

    Java 2023年5月20日
    00
  • Java四个线程常用函数超全使用详解

    Java四个线程常用函数超全使用详解 在Java多线程编程中,有四个常用的线程函数:wait(), notify(), notifyAll()和sleep()。这些函数被广泛使用,并涉及到线程同步、线程等待和线程唤醒等方面。在本篇文章中,我们将深入探讨这些函数的功能以及使用方法。 wait() wait()函数使当前线程进入等待状态,直到另一个线程调用not…

    Java 2023年5月18日
    00
  • Spring Security 图片验证码功能的实例代码

    下面我会给出关于“Spring Security 图片验证码功能的实例代码”的详细攻略。首先,我们需要思考一下问题,什么是图片验证码,为什么要使用它。 图片验证码就是在需要用户输入验证码时,生成一张随机的图片,用户需要识别图片中的验证码才能通过验证。由于图片验证码中的验证码是随机生成的,所以可以有效地避免机器人或爬虫等自动化程序的攻击。 在Spring Se…

    Java 2023年5月20日
    00
  • javaMybatis映射属性,高级映射详解

    Java Mybatis 映射属性,高级映射详解 概述 在 Java Mybatis 中, 映射属性是指将 Java 对象映射到数据库表的字段上。Mybatis 提供了多种映射方式,这篇攻略主要介绍 Mybatis 映射属性的基本用法和高级映射。 基本映射 在 Mybatis 的 mapper 文件中,我们可以使用 resultMap 标签来对返回对象进行映…

    Java 2023年6月1日
    00
  • SpringMVC DispatcherServlet组件实现解析

    我来为你详细讲解“SpringMVC DispatcherServlet组件实现解析”的完整攻略。 1. 前言 在SpringMVC开发中,DispatcherServlet组件是非常重要的组件之一,它是整个MVC架构的核心。它负责将客户端的请求数据传递给对应的Controller进行处理,同时还负责将Controller处理的结果返回给客户端。Dispat…

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