为什么程序不会退出?

问题描述 投票:2回答:2

好的,所以我试图将阻塞网络请求转换为非阻塞请求。我用于网络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的内容,我知道如果内部线程因某种原因而死,它会创建一个新线程,并将状态安全地“传输”到新创建的线程中。我不知道为什么程序不会终止。有人可以给一些提示吗?

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

java multithreading concurrency executorservice
2个回答
1
投票

你混合了两种模式。

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

如果你自己创建线程,然后运行它,你应该join它。然后孩子的线程是你的。


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

© www.soinside.com 2019 - 2024. All rights reserved.