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

这里是关于“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基于C/S结构实现多线程聊天室

    Java基于C/S结构实现多线程聊天室的攻略如下: 确定需求和功能点 首先需要明确聊天室的功能,如聊天、发送文件、创建和加入房间等。然后确定需要实现的功能点,例如登录验证、用户管理、消息广播等。 选择合适的框架和技术 选择适合的框架和技术可以提高开发效率和应用性能。Java中可以选择基于Socket和ServerSocket类实现TCP连接,或者使用Nett…

    多线程 2023年5月16日
    00
  • Python基于gevent实现高并发代码实例

    Python基于gevent实现高并发代码实例 1. 前言 在网络编程中,我们经常会遇到高并发的情形,即有大量的请求同时涌向服务器,需要服务器能够快速响应并处理这些请求。在 Python 中,我们可以使用多线程或多进程等方式来实现高并发,但是这些方式在一定程度上会影响程序的性能。 这时,使用协程来实现高并发就是一个好的方案。Python 中有很多支持协程的第…

    多线程 2023年5月16日
    00
  • java基本教程之java线程等待与java唤醒线程 java多线程教程

    Java线程等待与唤醒线程 线程等待 线程等待就是让线程先暂停一下,等待特定的条件被满足时再继续执行,一般情况下会使用wait()方法进行线程等待。 wait()方法的用法: synchronized(monitorObject) { while(!conditionWarranted()) { monitorObject.wait(); } 代码中的mon…

    多线程 2023年5月16日
    00
  • Java经典面试题汇总–多线程

    Java经典面试题汇总–多线程 前言 在Java开发中涉及到多线程的知识点比较多,同时也是面试中经常涉及到的内容。因此,掌握Java多线程相关的知识是非常有必要的。 多线程基础 1. 多线程的定义 多线程指的是在一个程序中执行多个线程,执行的过程中它可以同时运行多个任务,可以使用多个CPU。多线程可以提高程序的并发性,从而提高系统的资源利用率和效率。 2.…

    多线程 2023年5月17日
    00
  • C#(asp.net)多线程用法示例(可用于同时处理多个任务)

    下面是C#(asp.net)多线程用法示例的完整攻略。 一、为什么需要用到多线程 在编写程序并处理任务时,通常会遇到需要同时处理多个任务的情况,如果使用单线程去处理这些任务,由于任务之间的相互制约和耗时不同,在某个任务没有完成时,程序就会被阻塞,导致程序运行速度慢,用户体验不佳。而多线程则可以让这些任务同时执行,提高程序的执行效率和响应速度。 二、如何使用多…

    多线程 2023年5月17日
    00
  • python 包之 threading 多线程

    首先,我们来介绍一下什么是 Python 的 threading 包。 Python 的 threading 包提供了对线程操作的支持。线程表示一个独立的控制流,它允许我们同时执行多个流程。对于 Python 程序,即使没有手动创建过线程,也会默认有一个主线程,它会在程序启动时自动创建。同时,Python 还提供了一些库函数,可以在任意时刻操作线程。 下面,…

    多线程 2023年5月17日
    00
  • 详解三种java实现多线程的方式

    详解三种java实现多线程的方式 在Java中,实现多线程有3种方式:继承Thread类、实现Runnable接口以及使用Callable和Future接口。每种方式都有自己的优缺点,具体实现方式如下: 继承Thread类 Java的每个线程都是通过Thread类的实例来实现的,因此第一种实现多线程的方式是创建继承自Thread类的子类,重写run()方法。…

    多线程 2023年5月17日
    00
  • C++11 并发指南之多线程初探

    C++11 并发指南之多线程初探 什么是多线程 多线程是指在一个进程中运行的多个不同执行流程,每个执行流程叫做一个线程。多线程可以使程序并行执行,提高程序效率。 为什么要使用多线程 在单线程程序中,程序按照顺序执行,如果程序中出现了耗时的操作,程序就会变得非常慢。使用多线程可以使程序中的耗时操作在不同的线程中执行,从而提高程序的执行效率。另外,多线程也可以使…

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