简体   繁体   English

为什么程序不退出?

[英]Why won't the program exit?

Okay, so I was trying to convert a blocking network request to a non-blocking request.好的,所以我试图将阻塞网络请求转换为非阻塞请求。 The library that I'm using for network I/O does provide functions to make asynchronous HTTP calls, but anyways, for the sake of experiments, I tried to do it this way:我用于网络 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();
        }
    }
}

I'm not a pro programmer and an absolute beginner when it comes to concurrency, and even I could tell that this piece of code can be improved, at least bit (one of those feelings you have as a beginner when you know something is wrong, but not sure what is).我不是专业程序员,也不是并发方面的绝对初学者,我什至可以说这段代码可以改进,至少可以改进一点(当你知道某些事情有问题时,你作为初学者的感受之一,但不确定是什么)。 Anyways, what confuses me about the code above is that the program does not terminate.无论如何,让我对上面代码感到困惑的是程序不会终止。 I didn't expect that to happen.我没想到会发生这种情况。 I read a bit about Executors.singleThreadExecutor and I have an idea that if the inner thread dies for some reason, it creates a new thread and "transports" the state safely to the newly created thread.我读了一些关于Executors.singleThreadExecutor ,我有一个想法,如果内部线程由于某种原因死亡,它会创建一个新线程并将状态安全地“传输”到新创建的线程。 I've no clue why the program does not terminate though.我不知道为什么程序没有终止。 Can someone give some hints?有人可以给一些提示吗?

Please note that the code provided here will not be used in production environments.请注意,此处提供的代码不会用于生产环境。 I wrote this just for practice.我写这个只是为了练习。

You are mixing two patterns.您正在混合两种模式。

If you are using executor s, you don't need to join.如果您使用的是executor ,则不需要加入。 That thread was started by a system thread, not your main thread.该线程是由系统线程启动的,而不是您的主线程。 It is not your child thread, actually you cannot join it.它不是您的子线程,实际上您无法join它。 Just fire and forget.只是开火然后忘记。

If you create the thread yourself, then run it, you should join it.如果你自己创建线程,然后运行它,你应该join它。 Then the child thread is yours.那么子线程就是你的了。

Your problem here is that the thread in your executor service is not a daemon thread.您的问题是您的执行程序服务中的线程不是守护线程。 If you supply a ThreadFactory when you create your executor, then it should work.如果您在创建执行程序时提供ThreadFactory ,那么它应该可以工作。

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

This will produce a executor service with daemon threads.这将产生一个带有守护线程的执行器服务。 You also have a bit of a race condition with your 'sleep'.你的“睡眠”也有一些竞争条件。 Instead of join , use a CountdownLatch .使用CountdownLatch代替join

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM