Java多线程阻塞与唤醒代码示例

下面是Java多线程阻塞与唤醒代码示例的完整攻略。

前置知识

在开始讲解Java多线程阻塞与唤醒代码示例之前,需要掌握以下知识点:

  • 多线程的概念与基本操作,如创建线程、线程同步等;
  • 线程阻塞与唤醒的概念与使用方法,如wait()、notify()、notifyAll()等;
  • 线程状态的概念与使用,如Thread.State等。

示例一:生产者与消费者问题

生产者与消费者问题是一个非常经典的多线程问题,常用于考察多线程的基本操作、线程同步、线程阻塞与唤醒等知识点。下面给出一个生产者与消费者问题的代码示例:

public class ProducerConsumerExample {
    private static final int BUFFER_SIZE = 10;
    private static Queue<Integer> buffer = new LinkedList<>();

    public static void main(String[] args) {
        Thread producer = new ProducerThread();
        Thread consumer = new ConsumerThread();
        producer.start();
        consumer.start();
    }

    private static class ProducerThread extends Thread {
        @Override
        public void run() {
            int i = 0;
            while (true) {
                synchronized (buffer) {
                    if (buffer.size() < BUFFER_SIZE) {
                        buffer.offer(i++);
                        System.out.println("ProducerThread: Produced " + i);
                        buffer.notify();
                    } else {
                        try {
                            buffer.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    private static class ConsumerThread extends Thread {
        @Override
        public void run() {
            while (true) {
                synchronized (buffer) {
                    if (!buffer.isEmpty()) {
                        int value = buffer.poll();
                        System.out.println("ConsumerThread: Consumed " + value);
                        buffer.notify();
                    } else {
                        try {
                            buffer.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

上述代码实现了一个生产者与消费者协作的模型,生产者线程向一个固定长度的缓冲区中生产数字,消费者线程从缓冲区中取出数字并打印。其中,ProducerThread和ConsumerThread分别是生产者和消费者的线程类,buffer是一个缓冲区队列,BUFFER_SIZE是缓冲区队列的容量。线程协作的具体实现如下:

  1. 在生产者线程中,判断缓冲区队列是否已经满了,如果没有就生产一个数字插入队列,并调用buffer.notify()方法唤醒等待的消费者线程,否则就调用buffer.wait()方法进入等待状态。
  2. 在消费者线程中,判断缓冲区队列是否为空,如果不为空就取出一个数字打印,并调用buffer.notify()方法唤醒等待的生产者线程,否则就调用buffer.wait()方法进入等待状态。

通过上述代码示例,我们可以了解到Java多线程阻塞与唤醒的具体使用方法,并且实现了经典的生产者与消费者问题。

示例二:线程池的阻塞队列

线程池是一个非常常用的多线程技术,实现线程池需要使用到阻塞队列。下面给出一个线程池的阻塞队列的代码示例:

public class ThreadPoolWithBlockingQueueExample {
    private static final int POOL_SIZE = 2;
    private static final int TASK_NUM = 5;
    private static final int QUEUE_SIZE = 3;
    private static ExecutorService threadPool = new ThreadPoolExecutor(
            POOL_SIZE,
            POOL_SIZE,
            0L,
            TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(QUEUE_SIZE),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < TASK_NUM; i++) {
            int taskId = i + 1;
            threadPool.execute(() -> {
                System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        threadPool.shutdown();
        while (!threadPool.awaitTermination(100L, TimeUnit.MILLISECONDS)) {
            System.out.println("Wait for thread pool termination");
        }
        System.out.println("Thread pool is terminated");
    }
}

上述代码实现了一个线程池的阻塞队列模型,其中,ThreadPoolWithBlockingQueueExample是程序入口类,POOL_SIZE是线程池的核心线程数,TASK_NUM是任务的数量,QUEUE_SIZE是阻塞队列的大小,threadPool是线程池对象。线程协作的具体实现如下:

  1. 在main函数中,使用for循环向线程池中提交任务,每个任务都会打印一句话,并且线程会睡眠1s模拟任务执行时间。
  2. 在提交任务之后,调用threadPool.shutdown()方法关闭线程池,并且使用threadPool.awaitTermination()方法等待线程池中的线程执行完毕。
  3. 在等待线程池中的线程执行完毕的过程中,程序会不断打印"Wait for thread pool termination",直到线程池中的线程执行完毕,程序才会打印"Thread pool is terminated"。

通过上述代码示例,我们可以了解到线程池的阻塞队列是如何阻塞和唤醒线程的,以及如何正确地关闭线程池。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程阻塞与唤醒代码示例 - Python技术站

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

相关文章

  • Java通过jersey实现客户端图片上传示例

    下面是实现“Java通过jersey实现客户端图片上传示例”的攻略。 准备工作 确保已经安装好Java开发环境和Maven。 在Maven中加入Jersey的依赖,例如: <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-serv…

    Java 2023年5月19日
    00
  • Java根据控制台实现定位异常

    下面是关于“Java根据控制台实现定位异常”的完整攻略: 1. 什么是控制台? 控制台指的是操作系统提供的一种命令行界面,用户可以在其中通过命令执行一些操作或查看一些信息。在Java中,System.out和System.err就是控制台输出的方式。 2. 为什么要根据控制台来定位异常? 在Java程序运行时,如果发生异常,通常会在控制台输出相关的错误信息。…

    Java 2023年5月27日
    00
  • Springboot之自定义全局异常处理的实现

    关于“Springboot之自定义全局异常处理的实现”的完整攻略,我将从以下几个方面进行详细讲解: 为什么需要自定义全局异常处理 Springboot中全局异常处理的实现方式 自定义全局异常处理的实现步骤及示例说明 1. 为什么需要自定义全局异常处理? 在开发过程中,我们经常遇到各种异常情况,如空指针异常、参数异常、文件未找到等等,这些异常会导致程序崩溃或者…

    Java 2023年5月27日
    00
  • @OneToMany查询陷入循环引用的解决方案

    当在实体类中使用@OneToMany注解定义一对多关系时,会出现查询数据时陷入循环引用的问题,导致查询效率低下。以下是解决方案的完整攻略: 1. 方案一:使用@JsonIgnore解决循环引用 @JsonIgnore注解可以用来忽略在实体类之间的相互依赖关系。加上该注解后,在查询数据时就可以排除循环引用导致的无限循环。 public class User {…

    Java 2023年5月20日
    00
  • Java 数组转List的四种方式小结

    Java 数组转 List 的四种方式小结 在 Java 开发中,数组和 List 是非常常见的数据类型。有时我们需要将数组转换成 List 以便进行操作。本文将介绍四种将 Java 数组转换成 List 的常用方法。 方法一:使用 Arrays.asList() Arrays 类提供了一个 asList() 方法,可以将数组转换成 List。 SomeTy…

    Java 2023年5月26日
    00
  • java对象拷贝详解及实例

    首先我们需要明确一下,Java中的对象拷贝指的是拷贝一个对象的副本,而不是两个对象共享同一块内存地址。在Java中,我们可以使用浅拷贝和深拷贝两种方式来实现对象的拷贝。 浅拷贝 浅拷贝最简单的方式就是使用Object类的clone()方法,该方法可以复制一个Java对象。但是,它并不是完全的复制。当我们使用clone()方法来复制一个Java对象时,它会返回…

    Java 2023年5月26日
    00
  • struts中动态方法调用使用通配符

    在Struts框架中,可以通过动态方法调用使用通配符的方式,实现对请求URL的自动解析,从而找到对应的Action类及其方法进行处理。 以下是使用通配符的完整攻略: 1. 配置struts.xml 在struts.xml中,可以配置动态方法调用的命名空间及通配符等参数。如下所示: <package name="example" na…

    Java 2023年5月20日
    00
  • SpringBoot 中使用JSP的方法示例

    Spring Boot是一个轻量级的框架,它可以快速地构建基于Java的Web应用程序。相比于Spring Framework而言,Spring Boot带来了更加方便的配置方式,同时也提供了一些默认的配置,让开发者快速构建应用程序。但是,在默认的情况下,Spring Boot并不支持JSP作为视图层,若要使用JSP需要另外进行配置。下面就是Spring B…

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