为什么程序不退出?

时间:2019-03-14 15:23:07

标签: 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.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();
        }
    }
}

在并发方面,我不是专业程序员,也不是绝对的初学者。即使我可以告诉我,这段代码也可以改进,至少可以改善一点(当您了解初学者时,其中的一种感觉)出了点问题,但不确定是什么)。无论如何,使我对上面的代码感到困惑的是该程序没有终止。我没想到会发生这种情况。我读了一些关于Executors.singleThreadExecutor的知识,并且我有一个想法,如果内部线程由于某种原因而死,它将创建一个新线程并将状态安全地“传输”到新创建的线程。我不知道为什么程序没有终止。有人可以给些提示吗?

请注意,此处提供的代码不会在生产环境中使用。我写这个只是为了练习。

2 个答案:

答案 0 :(得分:1)

您正在混合两种模式。

如果您使用的是executor,则无需加入。该线程是由系统线程而不是您的主线程启动的。它不是您的子线程,实际上您不能 join。只是开火而忘记。

如果您自己创建线程,然后运行它,则应join。那么子线程就是你的。

答案 1 :(得分:0)

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

Executors.newFixedThreadPool(1, 
  new ThreadFactory() {
    public Thread newThread(Runnable r) {
      Thread t = Executors.defaultThreadFactory.newThread(r);
      t.setDaemon(true);
      return t;
   }
});

这将产生带有守护程序线程的执行程序服务。 您的“睡眠”也有些比赛条件。 代替join,使用CountdownLatch