好的,所以我试图将阻止网络请求转换为非阻止请求。我用于网络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
的知识,并且我有一个想法,如果内部线程由于某种原因而死,它将创建一个新线程并将状态安全地“传输”到新创建的线程。我不知道为什么程序没有终止。有人可以给些提示吗?
请注意,此处提供的代码不会在生产环境中使用。我写这个只是为了练习。
答案 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
。