Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将可调用线程作为守护进程_Java_Multithreading - Fatal编程技术网

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();