Java多线程---线程的取消和关闭

启动一个线程是很容易的,无论是继承Thread类或者实现Runnable方法。大多数时候我们都是希望它能正常运行直到结束,或者自行停止。然而有时候我们希望能够提前结束线程,这个可能是用户取消了某个操作,或者应用程序需要快速关闭。

Java语言本身没有提供任何机制来安全的终结某个线程。但是提供了中断(Interruption),这是一种协作机制,能使一个线程终止另一个线程。这种协作式的机制式式很有必要的,因为我们很少需要一个线程立即停止,这样会造成数据不一致的状态(这就是Thread.stop()为什么被弃用的原因)。当需要停止时,首先清除当前正在执行的工作,然后再结束。

取消一个操作的原因

  • 用户请求取消。比如点击 “取消” 按钮
  • 有时间限制的操作。比如在有限时间内搜索问题解空间,并得到最优解。当计时器超时的时候,取消正在搜索的任务。
  • 应用程序事件。将上述搜索问题解空间的任务分解,当一个任务找到最佳解决方案后,则其他正在执行搜索任务的线程将被取消。
  • 错误。比如一个爬虫在搜索网页,并保存到磁盘。当磁盘满时,或者其他错误,所有的搜索任务都会结束。
  • 关闭。当一个程序或服务关闭时,对正在执行的任务平缓的关闭(即等待其继续执行完成),或立即关闭(取消任务)。

取消标志

设置一个表示“已请求取消”的标志,然后定期地查看该标志。如果设置了这个标志那么任务将提前结束。下面举个例子:

public class SimpleCancle implements Runnable{
   
    private volatile boolean flag;
    public void cancle(){
   flag = true;}
    @Override
    public void run() {
   
        int i = 0;
        while (!flag) {
   
            System.out.println(i++);
        }
        System.out.println("run is finished");
    }
    public static void main(String[] args) {
   
        SimpleCancle sample = new SimpleCancle();
        Thread test = new Thread(sample);
        test.start();
        try {
   
            Thread.sleep(200);
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }finally {
   
       		sample.cancle();
       	}
    }
}

这里的while循环如果没有设置标志位,那么会一直执行,消耗cpu时钟周期。通过这种设置标志位的行为进行取消可能会存在一定的延迟,就是说在调用cancle方法和run方法执行下一次检查之间可能存在延迟。在finally块中保证一定能取消。

中断

上述使用取消表示确实可以停止任务并退出,虽然可能存在一定的延迟。但是如果while循环中调用了一个阻塞的方法,比如BlockingQueue.put,那么这个任务可能永远不会检查标志,因此永远不会结束。
举个例子:

public class NeverStop implements Runnable{
   
    private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用多线程异步处理任务集中统一处理结果的方式有很多,其中比较常用的方式是使用线程池和Future对象。 1. 线程池:Java提供了Executor框架,可以通过创建线程池来管理多个线程。你可以使用ThreadPoolExecutor类来创建一个线程池,并将任务提交给线程池进行执行。通过使用线程池,你可以控制并发线程的数量,避免创建过多的线程导致资源浪费。当所有任务执行完成后,你可以通过线程池的回调机制来处理任务的结果。 2. Future对象:Future是Java提供的一个接口,它表示一个异步计算的结果。你可以通过ExecutorService.submit()方法提交一个任务,并返回一个Future对象。通过Future对象,你可以检查任务是否完成、取消任务的执行、获取任务的执行结果等。当所有任务都提交完成后,你可以遍历Future对象集合,获取每个任务的执行结果,并进行统一处理。 下面是一个示例代码,演示了如何使用线程池和Future对象来实现多线程异步处理任务集中统一处理结果: ```java import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class AsyncTaskProcessor { public static void main(String[] args) { // 创建线程池 ExecutorService executor = Executors.newFixedThreadPool(5); // 创建任务列表 List<Callable<Integer>> tasks = new ArrayList<>(); tasks.add(new Task(1)); tasks.add(new Task(2)); tasks.add(new Task(3)); try { // 提交任务并获取Future对象列表 List<Future<Integer>> futures = executor.invokeAll(tasks); // 处理任务结果 for (Future<Integer> future : futures) { if (future.isDone()) { int result = future.get(); System.out.println("Task result: " + result); // 统一处理任务结果 // ... } } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } // 关闭线程池 executor.shutdown(); } static class Task implements Callable<Integer> { private int taskId; public Task(int taskId) { this.taskId = taskId; } @Override public Integer call() throws Exception { // 执行任务逻辑 Thread.sleep(1000); return taskId * 10; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值