Java 常用API编程

目录

Java调用shell并打印输出结果

多线程 

FutureTask获取子线程返回值

ExecutorCompletionService获取多个子线程返回值

Java调用shell并打印输出结果


import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Process proc = Runtime.getRuntime().exec("pwd");
        InputStream inputStream = proc.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        proc.waitFor();
    }
}

多线程 

多线程部分,方便查找,就不拆分到其他篇了。

实现多线程的方式包括继承Thread,实现Runnable或Callable<V>接口,前两者是没有返回体的(Callable<V>的V即为我们返回体的数据类型),本篇不对前两种方式进行讲解,仅介绍Callable。

FutureTask获取子线程返回值

FutureTask适合开启单个子线程并在主线程中监控、阻塞获取子线程的返回值,由于其get()方法有阻塞,如果需要获取多个子线程的返回结果,主线程中需要等子线程挨个执行完(因为需要挨个获取执行结果),达不到好的多线程效果,以下是示例:

  • 先编写子线程类(不带任何逻辑,打印-睡3秒-返回结束语句):
import java.util.concurrent.Callable;
public class UglyRunner implements Callable<String> {
    @Override
    public String call() throws Exception {
        String threadName = Thread.currentThread().getName();
        System.out.println(String.format("%s start to run: %s", threadName, new Date()));
        System.out.println(threadName + ": Please hold on, I'm running....");
        Thread.sleep(3000);
        System.out.println(String.format("%s stop running: %s", threadName, new Date()));

        return threadName + ": I'm out now";
    }
}
  • 再编写主类(循环检查子线程执行是否完成,子线程执行完成后获取其返回值并打印):
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class WaitSubRes {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new UglyRunner());
        Thread thread = new Thread(futureTask);
        thread.start();
        // 每1秒循环检查一次子线程是否完成执行
        while (!futureTask.isDone()) {
            System.out.println(Thread.currentThread().getName() + ": the sub task is still running....");
            Thread.sleep(1000);
        }
        System.out.println(futureTask.get());
    }
}

以上代码,主线程循环检查了子线程的运行状态,并在子线程运行完毕后打印了子线程的返回值。接下来,尝试在启动主类中创建多个子线程。

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class WaitMultiSubRes {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        UglyRunner uglyRunner = new UglyRunner();
        for (int i = 0; i < 3; i++) {
            FutureTask<String> futureTask = new FutureTask<>(uglyRunner);
            executor.submit(futureTask);
            while (!futureTask.isDone()) {
                System.out.println(Thread.currentThread().getName() + ": the sub task is still running....");
                Thread.sleep(1000);
            }
            System.out.println(futureTask.get());
        }
        executor.shutdown();
    }
}

这里用了线程池的写法,不过无关大局。通过观察打印输出结果,可以发现三个子线程是顺序执行的(红线框为开始时间,绿线框为结束时间):

实际开发中,我们肯定不喜欢这样的结果,阻塞影响了多线程只能逐个进行,需要换一种方法,下面介绍。

ExecutorCompletionService获取多个子线程返回值

ExecutorCompletionService提供的take()方法可以阻塞获取子线程返回值,批量任务的返回值只需调用同样次数的take()即可,先完成运行的子线程返回值先被获取到。以下为相关代码:

import java.util.concurrent.*;


public class WaitMultiSubRes2 {
    public static int nThreads = 3;

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        UglyRunner uglyRunner = new UglyRunner();
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletionService<String> completionService = new ExecutorCompletionService<>(executorService);

        for (int i = 0; i < nThreads; i++) {
            completionService.submit(uglyRunner);
        }
        String result = "";
        for (int i = 0; i < nThreads; i++) {
            result = String.format("%s %s", result, completionService.take().get());
        }
        System.out.println(result);
        executorService.shutdown();

    }
}

运行结果:

可以看到,3个子线程在同一时间并行启动,而不是FutureTask那样串行启动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏舟飞流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值