Java并发编程示例(六):等待线程执行终止

yizhihongxing

这里是关于“Java并发编程示例(六):等待线程执行终止”的完整攻略。

标题

Java并发编程示例(六):等待线程执行终止

简介

在Java并发编程中,常常需要等待一个线程或多个线程的执行终止,才能接着执行下一步的操作。这篇文章将介绍如何等待线程执行终止的几种方法,以及使用这些方法的示例。

阻塞等待线程执行终止的方法

  1. 使用Thread.join()方法

在主线程中调用Thread.join()方法,可以等待另一个线程执行完毕后再执行主线程。示例代码如下:

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});
t.start();
t.join(); // 阻塞当前线程,等待t线程执行完毕
// do something after t thread completes
  1. 使用CountDownLatch

CountDownLatch是Java提供的一个同步工具类。通过它,可以设置一个计数器,当计数器变为0时,主线程才能继续执行。示例代码如下:

CountDownLatch latch = new CountDownLatch(1);
Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something
        latch.countDown(); // 计数器减1
    }
});
t.start();
latch.await(); // 阻塞当前线程,等待计数器变为0
// do something after t thread completes
  1. 使用CyclicBarrier

CyclicBarrier也是Java提供的一个同步工具类。它可以等待一组线程全部执行完毕后再执行主线程。示例代码如下:

CyclicBarrier barrier = new CyclicBarrier(2); // 2表示有2个线程需要等待
Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something
        try {
            barrier.await(); // 等待其他线程执行完毕
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
});
t.start();
barrier.await(); // 阻塞当前线程,等待t线程执行完毕
// do something after t thread completes

案例说明

  1. 使用Thread.join()方法

使用Thread.join()方法可以实现一个简单的多线程下载器。下载器启动多个线程同时下载文件,主线程等待所有线程下载完毕后再合并文件。

代码示例:

public class MultiThreadDownloader {

    private static final String FILE_URL = "http://example.com/bigfile.zip";

    private static final String FILE_PATH = "bigfile.zip";

    private int threadCount;

    private volatile int finishedThreadCount;

    public MultiThreadDownloader(int threadCount) {
        this.threadCount = threadCount;
    }

    public void download() throws IOException, InterruptedException {
        URL url = new URL(FILE_URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        int responseCode = conn.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            throw new RuntimeException("HTTP response code is " + responseCode);
        }

        int fileLength = conn.getContentLength();
        RandomAccessFile file = new RandomAccessFile(FILE_PATH, "rw");
        file.setLength(fileLength);

        int blockSize = fileLength / threadCount;
        CountDownLatch latch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            long startPosition = i * blockSize;
            long endPosition = (i == threadCount - 1) ? fileLength - 1 : startPosition + blockSize - 1;
            new DownloadThread(startPosition, endPosition, i, latch).start();
        }

        latch.await();

        file.close();
        System.out.println("Download completed.");
    }

    private class DownloadThread extends Thread {
        private long startPosition;
        private long endPosition;
        private int threadId;
        private CountDownLatch latch;

        public DownloadThread(long startPosition, long endPosition, int threadId, CountDownLatch latch) {
            this.startPosition = startPosition;
            this.endPosition = endPosition;
            this.threadId = threadId;
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(FILE_URL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
                int responseCode = conn.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_PARTIAL) {
                    throw new RuntimeException("HTTP response code is " + responseCode);
                }

                InputStream in = conn.getInputStream();
                RandomAccessFile file = new RandomAccessFile(FILE_PATH, "rw");
                file.seek(startPosition);

                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    file.write(buffer, 0, bytesRead);
                }

                in.close();
                file.close();

                finishedThreadCount++;
                System.out.println("Thread " + threadId + " finished downloading.");

                if (finishedThreadCount == threadCount) {
                    latch.countDown();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        MultiThreadDownloader downloader = new MultiThreadDownloader(4);
        downloader.download();
    }
}
  1. 使用CyclicBarrier

使用CyclicBarrier可以实现一个简单的多线程排序器。排序器分配多个线程同时执行排序,主线程等待所有线程排序完毕后再合并结果。

代码示例:

public class MultiThreadSorter {

    private int threadCount;

    private int[] data;

    private CyclicBarrier barrier;

    public MultiThreadSorter(int threadCount, int[] data) {
        this.threadCount = threadCount;
        this.data = data;
        this.barrier = new CyclicBarrier(threadCount, new Runnable() {
            @Override
            public void run() {
                mergeSort();
            }
        });
    }

    public void sort() {
        int blockSize = data.length / threadCount;
        for (int i = 0; i < threadCount; i++) {
            int start = i * blockSize;
            int end = (i == threadCount - 1) ? data.length - 1 : start + blockSize - 1;
            new SortThread(start, end, barrier).start();
        }
    }

    private void mergeSort() {
        int[] temp = new int[data.length];
        mergeSort(data, temp, 0, data.length - 1);
    }

    private void mergeSort(int[] arr, int[] temp, int start, int end) {
        if (start >= end) {
            return;
        }

        int mid = start + (end - start) / 2;
        mergeSort(arr, temp, start, mid);
        mergeSort(arr, temp, mid + 1, end);
        merge(arr, temp, start, mid, end);
    }

    private void merge(int[] arr, int[] temp, int start, int mid, int end) {
        System.arraycopy(arr, start, temp, start, end - start + 1);

        int i = start;
        int j = mid + 1;
        for (int k = start; k <= end; k++) {
            if (i > mid) {
                arr[k] = temp[j++];
            } else if (j > end) {
                arr[k] = temp[i++];
            } else if (temp[i] < temp[j]) {
                arr[k] = temp[i++];
            } else {
                arr[k] = temp[j++];
            }
        }
    }

    private class SortThread extends Thread {
        private int start;
        private int end;
        private CyclicBarrier barrier;

        public SortThread(int start, int end, CyclicBarrier barrier) {
            this.start = start;
            this.end = end;
            this.barrier = barrier;
        }

        @Override
        public void run() {
            Arrays.sort(data, start, end + 1);
            try {
                barrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        int[] data = { 5, 9, 3, 7, 1, 8, 2, 6, 4 };
        MultiThreadSorter sorter = new MultiThreadSorter(4, data);
        sorter.sort();
        System.out.println(Arrays.toString(data));
    }
}

以上就是等待线程执行终止的几种方法及示例说明。希望对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程示例(六):等待线程执行终止 - Python技术站

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

相关文章

  • JAVA多线程和并发基础面试问答(翻译)

    为了实现该攻略,首先我们需要明确一些关键点,如何理解多线程和并发,以及一些常见的面试问题和答案。 理解多线程和并发 在理解多线程和并发之前,先需要知道进程和线程的概念。 进程 在计算机科学中,进程是一个电脑程序运行时的实例。一个程序至少有一个进程。在操作系统中,进程是资源分配和调度的一个单位,每个进程都有其专用的地址空间、代码段、数据段和系统栈。 线程 线程…

    多线程 2023年5月16日
    00
  • 详解易语言的多线程模块

    详解易语言的多线程模块攻略 什么是多线程 多线程是指在一个程序中同时执行多个不同的线程,各个线程之间可以并发执行,从而达到提高程序运行效率的目的。 易语言的多线程模块 易语言是一种基于事件驱动的编程语言,由于易语言的特点,在没有多线程的情况下,很难高效地完成某些任务。为了解决这个问题,易语言提供了多线程模块,可以在一个程序中同时执行多个线程,实现任务的并发处…

    多线程 2023年5月17日
    00
  • Java 高并发九:锁的优化和注意事项详解

    Java 高并发九:锁的优化和注意事项详解攻略 在并发编程中,锁是一种重要的同步机制,能够保证并发环境下的安全性和正确性。在 Java 中,锁主要通过 Synchronized、ReentrantLock 等工具来实现,但是如果锁的使用不当会导致程序性能下降或者死锁等问题。因此,本文将详细讲解锁的优化和注意事项。 一、锁优化的种类 1.1. 减小同步代码块的…

    多线程 2023年5月16日
    00
  • Java httpClient连接池支持多线程高并发的实现

    Java httpClient是一种开源的基于Http的请求和响应类型,它可以通过连接池技术适用于高并发的请求场景,下面是httpClient连接池支持多线程高并发的实现攻略: 1. 引入依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <art…

    多线程 2023年5月16日
    00
  • java并发编程专题(四)—-浅谈(JUC)Lock锁

    Java并发编程专题(四)–浅谈JUC Lock锁 1. Lock锁的介绍 Lock是Java编程语言提供的一种基于内存的锁方式,和synchronized关键字一样,都是为了实现资源的线程安全性。 但是与synchronized关键字不同,Lock是一个接口,而且需要开发者显式地获取和释放锁,从而更加灵活地控制多线程资源之间的互斥访问。 2. Lock的…

    多线程 2023年5月16日
    00
  • JS前端并发多个相同的请求控制为只发一个请求方式

    JS前端并发多个相同的请求时,由于后端可能要对请求做一些处理和计算,重复的请求将会对系统造成一定的负担和影响响应速度。因此,需要控制多个相同请求只发送一个请求的方式,以提高页面性能和后端服务的质量。下面是可能的解决方案: 1. 建立请求队列 可以通过建立请求队列,将所有重复的请求都放到队列中,然后只发出队列里的第一个请求。接着,在请求的回调中,从队列中移除发…

    多线程 2023年5月16日
    00
  • 并发数据库压力测试的shell脚本代码

    要进行并发数据库压力测试,可以使用ab(Apache Bench)工具。使用shell脚本代码可以简化测试过程,并且可以多次执行测试以获得可靠的结果。 以下是一个示例shell脚本,用于进行简单的并发数据库压力测试: #!/bin/bash # 设置测试参数 url="http://localhost:8080/api/users" co…

    多线程 2023年5月17日
    00
  • C++同步线程实现示例详解

    下面是详细讲解“C++同步线程实现示例详解”的完整攻略,包含两条示例说明。 C++同步线程实现示例详解 概述 在 C++ 中,线程同步是一种重要的技术,用于保证多个线程之间的协调与同步,有效避免竞争与错误。本文将详细介绍 C++ 中线程同步的实现方法,并提供两个示例说明。 互斥锁 互斥锁是 C++ 中线程同步的一种常用方式,可以用于在多个线程之间控制访问共享…

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