Java 为什么赢了';程序不能退出吗?

Java 为什么赢了';程序不能退出吗?,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,好的,所以我试着将阻塞网络请求转换为非阻塞请求。我用于网络I/O的库确实提供了进行异步HTTP调用的函数,但无论如何,为了实验起见,我尝试这样做: import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; import com.mashape.unirest.r

好的,所以我试着将阻塞网络请求转换为非阻塞请求。我用于网络I/O的库确实提供了进行异步HTTP调用的函数,但无论如何,为了实验起见,我尝试这样做:

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class TestExecutorService {
    private static final ExecutorService executor = Executors.newSingleThreadExecutor();
    static volatile Thread innerThread;

    public static void asyncGet (String url) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                innerThread = Thread.currentThread();
                GetRequest request = Unirest.get(url);
                try {
                    HttpResponse <String> response = request.asString();
                    System.out.println(response.getBody());
                    Unirest.shutdown();
                } catch (UnirestException exc) {
                    exc.printStackTrace();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        });
    }
}
public class Main {
    public static void main(String[] args) {
        TestExecutorService.asyncGet("https://stackoverflow.com");
        System.out.println("We're already here!");

        try {
            // Delay so that executor service's thread object could be
            // ...assigned to static variable innerThread
            Thread.sleep(100);
            TestExecutorService.innerThread.join();
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}
import com.mashape.unirest.http.HttpResponse;
导入com.mashape.unirest.http.unirest;
导入com.mashape.unirest.http.exceptions.uniresteption;
导入com.mashape.unirest.request.GetRequest;
导入java.io.IOException;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
类TestExecutorService{
private static final executor service executor=Executors.newSingleThreadExecutor();
静态易失性线程;
公共静态void asyncGet(字符串url){
executor.execute(新的Runnable(){
@凌驾
公开募捐{
innerThread=Thread.currentThread();
GetRequest=Unirest.get(url);
试一试{
HttpResponse response=request.asString();
System.out.println(response.getBody());
Unirest.shutdown();
}捕获(UnirestException){
exc.printStackTrace();
}捕获(ioe异常ioe){
ioe.printStackTrace();
}
}
});
}
}
公共班机{
公共静态void main(字符串[]args){
TestExecutorService.asyncGet(“https://stackoverflow.com");
System.out.println(“我们已经到了!”);
试一试{
//延迟,以便执行器服务的线程对象可以
//…分配给静态变量innerThread
睡眠(100);
TestExecutorService.innerThread.join();
}捕获(中断异常ie){
即printStackTrace();
}捕获(ioe异常ioe){
ioe.printStackTrace();
}
}
}
我不是一个专业程序员,在并发性方面也不是一个绝对的初学者,甚至我可以说这段代码可以改进,至少可以改进一点(当你知道有什么问题,但不确定是什么问题时,作为一个初学者,你会有这种感觉)。无论如何,上面的代码让我困惑的是程序没有终止。我没想到会发生这种事。我读了一些关于执行器的文章。singleThreadExecutor,我有一个想法,如果内线程由于某种原因死亡,它会创建一个新线程,并将状态安全地“传输”到新创建的线程。我不知道为什么程序没有终止。有人能给点提示吗


请注意,此处提供的代码不会用于生产环境。我写这篇文章只是为了练习。

您这里的问题是executor服务中的线程不是守护进程线程。如果在创建executor时提供
ThreadFactory
,那么它应该可以工作

Executors.newFixedThreadPool(1, 
  new ThreadFactory() {
    public Thread newThread(Runnable r) {
      Thread t = Executors.defaultThreadFactory.newThread(r);
      t.setDaemon(true);
      return t;
   }
});
这将产生一个带有守护进程线程的执行器服务。 你的“睡眠”也有一点种族问题。
不要使用
join
,而是使用
countdownlock

混合两种模式

如果您使用的是
executor
s,则无需加入。该线程是由系统线程而不是主线程启动的。它不是您的子线程,实际上您不能
加入它。只要开火就可以了


如果你自己创建线程,然后运行它,你应该加入它。那么子线程就是你的了。

是的……我知道可能的争用条件,但是由于程序足够小,如果发生这种情况,我将得到一个NullPointerException,我决定让线程休眠一段时间。无论如何,谢谢。我必须查一下什么是守护线程:)谢谢。在main中调用
asyncGet
之后,删除
innerThread
变量并在
executor
上调用
shutdown
,似乎可以解决问题。