Java 将可调用线程作为守护进程
如何使可调用线程成为守护进程线程 这就是我正在尝试的。我试图执行一组线程,其中一个线程没有完成,进入无限循环。它所做的是,即使执行了所有代码语句,程序的主线程也不会终止。之后,主线程进入挂起模式 下面是同样的代码片段Java 将可调用线程作为守护进程,java,multithreading,Java,Multithreading,如何使可调用线程成为守护进程线程 这就是我正在尝试的。我试图执行一组线程,其中一个线程没有完成,进入无限循环。它所做的是,即使执行了所有代码语句,程序的主线程也不会终止。之后,主线程进入挂起模式 下面是同样的代码片段 public class MyThread implements Callable<String> { private int value; public MyThread(int value) { this.value = valu
public class MyThread implements Callable<String> {
private int value;
public MyThread(int value) {
this.value = value;
}
@Override
public String call() throws Exception {
//Thread.currentThread().setDaemon(true);
System.out.println("Executing - " + value);
if (value == 4) {
for (; ; );
}
return value + "";
}
}
公共类MyThread实现可调用{
私有int值;
公共MyThread(int值){
这个值=值;
}
@凌驾
公共字符串调用()引发异常{
//Thread.currentThread().setDaemon(true);
System.out.println(“执行-”+值);
如果(值==4){
对于(;);
}
返回值+“”;
}
}
主程序
public class ExecutorMain {
public static String testing() {
ExecutorService executor = null;
List<Future<String>> result = null;
String parsedValue = null;
try {
executor = Executors.newSingleThreadExecutor();
List<MyThread> threads = new ArrayList<MyThread>();
for (int i = 1; i < 10; i++) {
MyThread obj = new MyThread(i);
threads.add(obj);
}
result = executor.invokeAll(threads, Long.valueOf("4000"), TimeUnit.MILLISECONDS);
//result = executor.invokeAll(threads);
for (Future<String> f : result) {
try {
parsedValue = f.get();
System.out.println("Return Value - " + parsedValue);
} catch (CancellationException e) {
System.out.println("Cancelled");
parsedValue = "";
f.cancel(true);
}
}
executor.shutdownNow();
} catch (Exception e) {
System.out.println("Exception while running threads");
e.printStackTrace();
} finally {
List executedThreads = executor.shutdownNow();
System.out.println(executedThreads);
for (Object o : executedThreads) {
System.out.println(o.getClass());
}
}
System.out.println("Exiting....");
//System.exit(1);
return "";
}
public static void main(String[] args) {
testing();
}
}
公共类执行器main{
公共静态字符串测试(){
executor服务executor=null;
列表结果=空;
字符串parsedValue=null;
试一试{
executor=Executors.newSingleThreadExecutor();
List threads=new ArrayList();
对于(int i=1;i<10;i++){
MyThread obj=新的MyThread(i);
添加(obj);
}
结果=executor.invokeAll(线程,Long.valueOf(“4000”),时间单位为毫秒);
//结果=executor.invokeAll(线程);
对于(未来f:结果){
试一试{
parsedValue=f.get();
System.out.println(“返回值-”+parsedValue);
}捕获(取消异常e){
系统输出打印项次(“取消”);
parsedValue=“”;
f、 取消(真);
}
}
执行者。关机现在();
}捕获(例外e){
System.out.println(“运行线程时异常”);
e、 printStackTrace();
}最后{
List executethreads=executor.shutdownNow();
System.out.println(已执行线程);
for(对象o:已执行线程){
System.out.println(o.getClass());
}
}
System.out.println(“退出…”);
//系统出口(1);
返回“”;
}
公共静态void main(字符串[]args){
测试();
}
}
我从前面的问题中了解到,我必须将我的线程作为守护进程线程
如何使可调用线程成为守护进程线程
您需要使用新的ThreadFactory
来创建守护进程线程。请看下面的答案:
默认情况下,执行器在构建池时创建非守护进程线程。但是您可以注入自己的ThreadFactory
,它为池创建线程
例如:
executor = ExecutorService.newSingleThreadExecutor(new MyThreadFactory());
ThreadFactory
实现newThread
方法:
Thread newThread(Runnable r)
从我上面链接的答案复制而来,您可以像这样实现它:
class MyThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
}
你在问题中提到:
//Thread.currentThread().setDaemon(true)
是的,这不起作用,因为一旦线程启动,您就不能设置守护进程标志。这不是要使
可调用到守护进程。实际上,您希望使执行线程成为守护进程。您可以通过以下方式创建线程,使其成为守护进程:
executor = Executors.newSingleThreadExecutor(new ThreadFactory(){
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
仅将由ExecutorService
创建的线程
设置为守护进程是没有帮助的(尽管您确实需要这样做)。您可以将ExecutorService
线程设置为守护进程,如下所示:
executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
您遇到的真正问题是此代码块:
for (Future<String> f : result) {
try {
parsedValue = f.get();
System.out.println("Return Value - " + parsedValue);
} catch (CancellationException e) {
System.out.println("Cancelled");
parsedValue = "";
f.cancel(true);
}
}
executor.shutdownNow();
原因很简单,Future#get
方法“在必要时等待计算完成,然后检索其结果”。但是计算永远不会完成,因为它处于无限循环中。即使是来自ThreadPoolExecutor#shutdownNow
或Future#cancel(true)
的中断也不会对您有所帮助,因为您的Callable
代码没有执行阻塞操作或检查中断
在这里,您有两个选择:
使用Future#get
的形式,它需要长超时
参数
使用Future#isDone
确定Future#get
方法在实际调用Future#get
之前是否要返回值
谢谢蒂姆的详细解释。然而,你提出的解决方案并没有解决这个问题。问题在于,由于线程已进入无限循环,它不会检查任何线程中断,因此不会终止
在我的场景中,无限循环不是一个很好的例子,但我们试图完成的是,我们正在执行一个正则表达式,该正则表达式执行时间太长,中断检查是在matcher.find()调用之后进行的。因为find()不会在规定的时间内返回,而且find()方法也不会检查线程中断,所以我们面临着悬而未决的线程问题。最后,从url实现了InterruptableCharSequence并使其正常工作。奇怪-我们只是对默认值进行了一些讨论。这是当默认应用程序关闭功能为“不要”时发生的事情:)感谢Tim的详细解释。然而,你提出的解决方案并没有解决这个问题。问题是,由于线程已进入无限循环,它不会检查任何线程中断,因此不会终止。对,,,这不是问题,只要它是守护进程,并且您不阻止非守护进程线程等待它完成。我提到了不检查中断的问题。不管怎样,我很高兴你找到了答案。这东西很重要!:-)您正在事后添加无关的未发布的详细信息。其他一些答案是
parsedValue = f.get();