1

我有处理繁重任务的线程应用程序,我想根据外部标志信息触发强制停止线程。我尝试过以下设计,

public class HeavyTaskThread implements Runnable
{
   private boolean forceStop;

   public void run()
   {
     ..
     ..
     ..
     ..
   }
}

另一个事实是我无法控制方法中实现的逻辑流程run();它只是调用一些第三方程序。我正在尝试使用轻型内部线程类并在父线程上调用方法interrupt(),但这不起作用。

请建议任何模式....

4

5 回答 5

3

处理您无法控制的第三方代码活动的推荐方法是将其作为不同的进程启动。然后在需要强制停止代码时简单地终止进程。它比杀死线程更干净和安全,因为它不会影响父进程并且操作系统会负责清理任务。

于 2012-08-21T05:17:48.120 回答
1

如果第三方程序不响应中断或设置条件,一个讨厌的选项是尝试通过将键变量置空、关闭套接字或文件等来杀死它。并希望它优雅地终止。就像我说的,讨厌,但有时你必须做你必须做的事......

于 2012-08-21T04:51:03.317 回答
0

如果您调用的任何第三方程序run()永远不会返回,那么您就不走运了。如果它定期返回,你可以让它循环,检查一个 volatileforceStop布尔值并在它为真时退出循环:

private volatile boolean forceStop;

public void run()
{
    while(!forceStop) {
        ..
        ..
    }
}
于 2012-08-21T04:44:43.167 回答
0

虽然我会投票支持都铎王朝的答案,但极端情况下,如果你很绝望:

选项 A - 重建问题代码。

  • 使用您最喜欢的 java 反编译器并重新创建问题类。

  • 将检查添加Thread.currentThread().isInterrupted()run.

  • 编译,将修改后的类放在类路径中的原始库之前。

  • 如果原始 jar 已签名,您可能必须消除相关的签名工件。

选项 B - 方面 J

  • 检查方法的源代码,如有必要run,使用您最喜欢的 java 反编译器。

  • 在内部循环中确定一个合理的点,以便介入和停止。

  • 检查代码中的异常处理。有什么漏洞吗?

  • 注入代码:根据需要抛出异常、捕获异常等,从run.

于 2012-08-21T06:17:35.207 回答
0

这是最终的分析......用于杀死线程。

  1. 使用线程来控制程序 B 的执行。但是不允许通过线程停止进程,因为相关方法已被弃用(停止/暂停等)

  2. 使用 ThreadGroup(只有一个线程作为其成员)并在组上调用“销毁”。但它再次落在同一轨道上,因为在尝试销毁操作之前应该停止每个线程。

  3. Process/ProcessBuilder via Runtime 似乎是获取进程引用并调用destroy()、waitFor() 等的更好方法,正如用户@Tudor提到的那样。

这是我尝试过的确切概述的代码,它无法杀死,注释行 while(isValid()) 代表我的另一个 java 程序调用。



    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;

    class TaskWorker implements Callable {
        private final int number;

        public TaskWorker(int number) {
            this.number = number;
        }

        public Boolean call() throws InterruptedException {
            while (!Thread.currentThread().isInterrupted()) {
                myBusyFunction();
            }
            return true;
        }

        private boolean isValid() {
            return true;
        }

        private void myBusyFunction() {
            //while (isValid()) {
            System.out.println(number + ">....Working.....");
            //}
        }
    }

    public class Test {
        public static void main(final String[] args) {
            CompletionService cs = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
            Collection tasks = new ArrayList(10);
            tasks.add(new TaskWorker(1));
            List> futures = new ArrayList>(tasks.size());
            try {
                for (Callable task : tasks) {
                    futures.add(cs.submit(task));
                }
                //----
                for (int t = 0; t  result = cs.poll(10, TimeUnit.SECONDS);
                    if (result == null) {
                        System.out.println(new Date() + ":Worker Timedout:");
                        //So lets cancel the first futures we find that havent completed
                        for (Future future : futures) {
                            System.out.println("Checking future");
                            if (future.isDone()) {
                                continue;
                            } else {
                                future.cancel(true);
                                System.out.println("Cancelled");
                                break;
                            }
                        }
                        continue;
                    } else {
                        try {
                            if (result.isDone() && !result.isCancelled() && result.get()) {
                                System.out.println(new Date() + ":Worker Completed:");
                            } else if (result.isDone() && !result.isCancelled() && !result.get()) {
                                System.out.println(new Date() + ":Worker Failed");
                            }
                        } catch (ExecutionException ee) {
                            ee.printStackTrace(System.out);
                        }
                    }
                }
            } catch (InterruptedException ie) {
            } finally {
                //Cancel by interrupting any existing tasks currently running in Executor Service
                for (Future f : futures) {
                    f.cancel(true);
                }
            }
            System.out.println(new Date() + ":Done");
        }
    }

于 2012-08-21T19:49:22.987 回答