传统观点告诉我们,大批量企业Java应用程序应优先使用线程池来生成新的工作线程.使用java.util.concurrent使这简单明了.
但是,确实存在线程池不适合的情况.我目前正在努力的具体示例是使用InheritableThreadLocal,它允许ThreadLocal变量"传递"到任何生成的线程.使用线程池时,此机制会中断,因为工作线程通常不是从请求线程生成的,而是预先存在的.
现在有办法解决这个问题(线程本地可以显式传入),但这并不总是合适或实用.最简单的解决方案是按需生成新的工作线程,然后让它InheritableThreadLocal完成它的工作.
这让我们回到刚才的问题 - 如果我有一个高容量的网站,在这里用户请求的线程产卵关每个半打工作线程(即不使用线程池),这是怎么回事给JVM的一个问题?我们可能会谈论每秒创建几百个新线程,每个线程持续不到一秒钟.现代JVM是否能很好地优化这一点?我记得在Java中需要对象池的日子,因为对象创建很昂贵.从此变得不必要了.我想知道是否同样适用于线程池.
如果我知道要测量什么,我会对它进行基准测试,但我担心的是问题可能比用剖析器测量的更微妙.
注意:使用线程本地的智慧不是问题所在,所以请不要建议我不要使用它们.
我对某事感到困惑.我所知道的是,在现代计算机的普通CPU上可以并发运行的最大线程数范围为8到16个线程.另一方面,使用GPU可以同时运行数千个线程,而调度程序不会中断任何线程来安排另一个线程.在几个帖子中: Java虚拟机 - 最大线程数 https://community.oracle.com/message/10312772 人们说他们在普通CPU上同时运行数千个Java线程.这怎么可能?我怎么知道可以并发运行的最大线程数,以便我的代码根据底层架构自动动态调整它.
我目前正在学习Scala中的演员.本书建议使用该react方法代替receive,因为它允许系统使用更少的线程.
我已经读过为什么创建一个线程很昂贵.但什么是是,一旦你的线程(应保持在初始化之后男主角系统斯卡拉)的原因,让他们周围是昂贵?
主要是内存消耗吗?还是有其他原因吗?
所以基本上我今天需要优化这段代码.它试图找到由一些函数产生的最长序列的第一百万起始数:
public static void main(String[] args) {
int mostLen = 0;
int mostInt = 0;
long currTime = System.currentTimeMillis();
for(int j=2; j<=1000000; j++) {
long i = j;
int len = 0;
while((i=next(i)) != 1) {
len++;
}
if(len > mostLen) {
mostLen = len;
mostInt = j;
}
}
System.out.println(System.currentTimeMillis() - currTime);
System.out.println("Most len is " + mostLen + " for " + mostInt);
}
static long next(long i) {
if(i%2==0) {
return i/2;
} else {
return i*3+1; …Run Code Online (Sandbox Code Playgroud) 我有两个代码选项:
选项1
int myFunc() {
return new Random().nextInt();
}
Run Code Online (Sandbox Code Playgroud)
要么:
选项2
private static final Random random = new Random();
int myFunc() {
return random.nextInt();
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这option 2更具惯用性.我想知道它的有效性option 1.
在option 1我将只使用由给定种子生成的第一个数字.在option 2我选择种子并n使用该种子生成数字.IIUC对随机性的保证就是这个用例.
因此,我的问题是,如果我option 1多次打电话,是否对输出分布的一致性有任何保证?
我想在 Scala 2.11 中构建一个简单的服务器来监听套接字。它应该从套接字异步读取数据并将数据从 RxScala 传递到 Observable 中。
我有一个 Java ServerSocket,应该使用readData阻塞的方法从中读取数据。这个方法启动一次,一直运行到整个程序停止:
val server = new ServerSocket(port)
def readData(server: ServerSocket): Unit = ???
Run Code Online (Sandbox Code Playgroud)
当从套接字读取数据时,我发现了两种不同的方法来避免阻塞整个程序:
new Thread {
override def run(): Unit = {
readData(server)
}
}.start()
Run Code Online (Sandbox Code Playgroud)
和
Future {
blocking {
readData(server)
}
}
Run Code Online (Sandbox Code Playgroud)
因为 Future 中没有包装返回值,然后可以将其传递给其他任务,所以 Future 的唯一任务是使计算非阻塞。所以我想知道这些方法之间是否有更大的差异?查看 Future 的实现,它看起来还使用给定的块创建并运行 Runnable。那么,如果一个人有一个永远/长时间运行的任务而没有结果,那么这些方法之一是否更可取?
我的应用程序包含一个ListView每次选择项目时启动后台任务的应用程序.然后,后台任务在成功完成时更新UI上的信息.
但是,当用户快速点击一个又一个项目时,所有这些任务都会继续,最后一个任务将完成"获胜"并更新UI,无论最后选择了哪个项目.
我需要的是以某种方式确保此任务在任何给定时间只有一个实例运行,因此在开始新任务之前取消所有先前任务.
这是一个演示该问题的MCVE:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class taskRace extends Application {
private final ListView<String> listView = new ListView<>();
private final Label label = new Label("Nothing selected");
private String labelValue;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
// Simple UI
VBox root = new VBox(5);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
root.getChildren().addAll(listView, label);
// Populate the …Run Code Online (Sandbox Code Playgroud) 我确实知道平台线程很昂贵,因为它需要更多内存并且容易发生 CPU 上下文切换。
但是,在虚拟线程的情况下,少数平台线程可以服务难以想象的大量虚拟线程,虚拟线程是否仍然需要内存空间来钝化上下文/堆栈,然后将其附加到载体线程?
它对记忆有何影响?
为什么自旋 10000 个虚拟线程不会因内存不足而消亡,而 10000 个平台线程则会因内存不足而消亡?
他们都需要相同的堆栈吗?以及需要维护应用程序相关信息的上下文,对吧?
内存中是否存在仅适用于平台线程的额外开销,这就是我们说虚拟线程在内存中“更轻”的原因?如果是的话,是什么造成了这种差异?
我正在进行基于代理的模拟.1000万代理商.
代理商一次几天/几周都不做任何事情,当他们必须做某事时,它不是cpu密集型的(应该花费<1ms).
产生1000万个线程是否合理?我已经读了Thread/sleep和future这似乎大有可为.
对此类项目的任何建议或建议阅读将不胜感激.
考虑这个问题.
现在有很多原因导致创建线程的成本很高,特别是需要分配大量内存并且需要注册线程的事实.
现在考虑这段代码:
Thread thread = new Thread(new SomeRunnable());
thread.start();
Run Code Online (Sandbox Code Playgroud)
哪一部分是"昂贵的"部分?实际创建Thread对象的行还是启动线程的行?或两者?为什么我问的原因是因为我写一个游戏服务器的组件和我辩论,如果我要尽快播放器连接创建Thread对象,一旦玩家完成登录启动线程,还是应该我都在玩家完成登录后创建并启动线程.
考虑以下服务类别:
//Singleton service
public class InquiryService{
private final ExecutorService es = Executors. newSingleThreadExecutor();
private final CustomerService cs = new CustomerServiceImpl();
public String process(){
//Asynchronous calls to get info from CustomerService
Future<String> result = es.submit(()->{return cs.getCustomer()});
//Query database
//Perform logic et all
String customerName = result.submit.get();
//continue processing.
}
}
Run Code Online (Sandbox Code Playgroud)
上面的服务类具有一个ExecutorServiceas字段。如果说在process方法上有100个并发请求,那么剩下的(100-1)个请求是否需要等待线程可用性?
如何解决请求等待?我可以想到的一种选择是ExecutorService在process方法内实例化,使用和关闭。但是,线程池不是要重用吗?
另一个选项将作为运行new Thread(new FutureTask<>(() -> {return cs.getCustomer()}))。哪一种是正确的方法?
更新:-
根据评论和答案,ExecutorService要重用和频繁Thread创建新内容的成本很高。因此,另一个选择是依次运行服务调用。
java ×9
scala ×2
actor ×1
asynchronous ×1
clojure ×1
concurrency ×1
cpu ×1
future ×1
gpu ×1
java-21 ×1
jvm ×1
performance ×1
project-loom ×1
random ×1
threadpool ×1