博客
关于我
多线程编程基础
阅读量:479 次
发布时间:2019-03-06

本文共 5695 字,大约阅读时间需要 18 分钟。

多线程编程基础

进程与线程的基础概念

进程

进程是程序运行的核心单元,是系统资源分配和调度的基本单位。每个进程都有独立的代码和数据空间,进程间切换会产生一定的开销。

  • 进程的特点

    进程是一个程序的一次执行实例,通常包含代码段、数据段和堆栈段。它是系统调度的基本单位。

  • 多进程环境

    多进程允许多个任务同时运行,通过系统调度将CPU资源分配给各个进程。

线程

线程是进程中的一个独立执行单元,是CPU调度的基本单位。与进程相比,线程具有更小的粒度,线程切换开销更低。

  • 线程的定义

    线程是进程中的一个执行实体,负责执行包含在进程地址空间中的代码。每个线程有自己的运行栈和程序计数器,但共享进程的其他资源。

  • 线程的作用

    线程允许多个任务在进程内部同时执行,提升系统效率。

进程的三大特征

  • 独立性

    进程可以独立地分配和管理资源。

  • 动态性

    进程的状态可以随着运行环境发生改变。

  • 并发性

    多个进程可以同时运行,通过系统调度实现并发执行。

  • 启动进程的方法

    通过不同的方式可以启动新的进程,以下是常用的两种方法:

    方法一:使用ProcessBuilder

    ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig/all");
    Process p = pb.start();
    // 读取进程输出
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((temp = br.readLine()) != null) {
    System.out.println(temp);
    }

    方法二:使用Runtime.exec

    String cmd = "cmd " + "/c " + "ipconfig/all";
    Process process = Runtime.getRuntime().exec(cmd);
    // 读取进程输出
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
    while ((temp = br.readLine()) != null) {
    System.out.println(temp);
    }

    动态生成代码并编译执行

    // 删除已存在的文件
    File f = new File("T1.java");
    if (f.exists()) {
    f.delete();
    }
    // 生成代码文件
    PrintWriter pw = new PrintWriter(new FileWriter("T1.java"));
    pw.println("public class T1 {");
    pw.println("public static void main(String[] args) throws Exception {");
    pw.println("System.out.println(\"Hello Java!\");");
    pw.println("}}");
    pw.close();
    // 编译代码
    Process process = Runtime.getRuntime().exec("cmd /c javac T1.java");
    // 执行已编译的类
    process = Runtime.getRuntime().exec("cmd /c java T1");

    线程的实现方法

    线程可以通过不同的方式实现,以下是常用的四种方法:

    1. 继承Thread类

    public class LeftThread extends Thread {
    public void run() {
    for (int i = 0; i < 50; i++) {
    System.out.println("左手一个慢动作...");
    try {
    Thread.sleep(500);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }
    // 启动线程
    Thread t1 = new LeftThread();
    t1.start();

    2. 实现Runnable接口

    public class RightRunnable implements Runnable {
    public void run() {
    for (int i = 0; i < 50; i++) {
    System.out.println(Thread.currentThread().getName() + ":右手慢动作重播!");
    }
    }
    }
    // 启动线程
    Thread t2 = new Thread(new RightRunnable());
    t2.start();

    3. 使用Callable和Future

    public class MyCallable implements Callable
    {
    private int begin;
    private int end;
    public MyCallable(int begin, int end) {
    this.begin = begin;
    this.end = end;
    }
    public Integer call() throws Exception {
    System.out.println(Thread.currentThread() + "---" + begin + ".." + end);
    int res = 0;
    for (int i = begin; i <= end; i++) {
    res += i;
    }
    return res;
    }
    }
    // 使用FutureTask创建线程
    FutureTask
    ft = new FutureTask
    (new MyCallable(1, 100));
    Thread t = new Thread(ft);
    t.start();
    int sum = ft.get();

    4. 使用线程池

    public class T1 {
    public static void main(String[] args) throws Exception {
    ExecutorService es = Executors.newFixedThreadPool(3);
    Future[] fs = new Future[10];
    for (int i = 0; i < 10; i++) {
    Callable
    caller = new MyCallable(i * 1000 + 1, (i + 1) * 1000);
    fs[i] = es.submit(caller);
    }
    int res = 0;
    for (int i = 0; i < fs.length; i++) {
    Object obj = fs[i].get();
    if (obj instanceof Integer) {
    res += (Integer) obj;
    }
    }
    es.shutdown();
    System.out.println("Main:" + res);
    }
    }

    线程池的实现

    线程池通过管理线程的生命周期,优化了线程资源的使用。常用的线程池实现包括:

    固定线程池

    ExecutorService es = Executors.newFixedThreadPool(3);
    // 创建多个Callable任务,并提交到线程池
    for (int i = 0; i < 10; i++) {
    Callable
    task = () -> {
    // 实现具体的任务逻辑
    try {
    // 假设任务涉及计算
    System.out.println("正在计算:" + i);
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    };
    Future
    future = es.submit(task);
    // 等待任务完成
    future.get();
    }
    es.shutdown();

    可扩展线程池

    ExecutorService es = Executors.newCachedThreadPool();
    for (int i = 0; i < 100; i++) {
    Callable
    task = () -> {
    System.out.println("新任务提交:" + i);
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    };
    Future
    future = es.submit(task);
    // 等待任务完成
    future.get();
    }
    es.shutdown();

    线程间的通信与同步

    线程间的通信和同步至关重要,以下是一些常用的机制:

    同步机制

    • synchronized 关键字

      可以锁定特定方法或代码块,防止多个线程同时访问。

    • Lock 接口

      使用第三方库如LockUtils实现更细粒度的锁。

    通信机制

    • Wait/Notify

      通过等待和通知机制实现线程间的同步。

    • CountDownLatch

      用于等待多个线程的完成。

    • CyclicBarrier

      用于多个线程在完成各自任务后,等待于一个共同的点。

    线程的终止与资源收集

    线程的终止需要谨慎处理,以避免资源泄漏。系统提供了以下机制:

    终止线程

    public class T1 implements Runnable {
    private boolean running = true;
    public void run() {
    try {
    while (running) {
    System.out.println("线程在运行");
    Thread.sleep(100);
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    public static void main(String[] args) {
    Thread t = new Thread(new T1());
    try {
    Thread.sleep(2000);
    running = false;
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    t.interrupt();
    t.join();
    System.out.println("线程已终止");
    }
    }

    资源收集

    孤儿进程和僵尸进程是多线程环境中的常见问题,需要妥善处理:

    • 孤儿进程

      当父进程退出而子进程仍在运行时,孤儿进程会被init进程收养。

    • 僵尸进程

      当子进程退出但父进程未释放资源时,僵尸进程会占用系统资源,需及时回收。

    并行与并发的理解

    • 并行

      多个处理器同时执行相同任务,真正意义上的同时执行。

    • 并发

      通过时间片轮转,使得看起来多个任务同时执行,但实际上是交替执行的。

    多线程编程的优点

  • 资源利用更高效

    线程的创建和切换开销较低。

  • 吞吐量更高

    CPU资源得到充分利用,减少空转时间。

  • 扩展性更好

    通过增加处理器核心,系统性能得到显著提升。

  • 总结

    多线程编程是一种强大的编程范式,通过合理利用系统资源,可以显著提升程序的性能和响应速度。在实际应用中,选择合适的线程和同步机制至关重要,以确保程序的健壮性和稳定性。

    转载地址:http://xbbdz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现Luhn (Mod 10)Algorithm算法(附完整源码)
    查看>>
    Objective-C实现LZW编码(附完整源码)
    查看>>
    Objective-C实现MAC桌面暗水印(附完整源码)
    查看>>
    Objective-C实现mandelbrot曼德勃罗特集算法(附完整源码)
    查看>>
    Objective-C实现markov chain马尔可夫链算法(附完整源码)
    查看>>
    Objective-C实现MATLAB中Filter函数功能(附完整源码)
    查看>>
    Objective-C实现matrix exponentiation矩阵求幂算法(附完整源码)
    查看>>
    Objective-C实现MatrixMultiplication矩阵乘法算法 (附完整源码)
    查看>>
    Objective-C实现max non adjacent sum最大非相邻和算法(附完整源码)
    查看>>
    Objective-C实现max subarray sum最大子数组和算法(附完整源码)
    查看>>
    Objective-C实现max sum sliding window最大和滑动窗口算法(附完整源码)
    查看>>
    Objective-C实现MaxHeap最大堆算法(附完整源码)
    查看>>
    Objective-C实现MaximumSubarray最大子阵列(Brute Force蛮力解决方案)算法(附完整源码)
    查看>>
    Objective-C实现MaximumSubarray最大子阵列(动态规划解决方案)算法(附完整源码)
    查看>>
    Objective-C实现maxpooling计算(附完整源码)
    查看>>
    Objective-C实现max_difference_pair最大差异对算法(附完整源码)
    查看>>
    Objective-C实现max_heap最大堆算法(附完整源码)
    查看>>
    Objective-C实现MD5 (附完整源码)
    查看>>
    Objective-C实现md5算法(附完整源码)
    查看>>
    Objective-C实现MeanSquareError均方误差算法 (附完整源码)
    查看>>