gpt4 book ai didi

java - 代码性能比较,线程与非线程

转载 作者:行者123 更新时间:2023-12-03 10:38:59 24 4
gpt4 key购买 nike

我有一些与线程相关的问题,假设有以下代码。请忽略代码可能的低效率,我只对线程部分感兴趣。

//code without thread use
public static int getNextPrime(int from) {
int nextPrime = from+1;
boolean superPrime = false;
while(!superPrime) {
boolean prime = true;
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
}
}
if(prime) {
superPrime = true;
} else {
nextPrime++;
}
}
return nextPrime;
}

public static void main(String[] args) {
int primeStart = 5;
ArrayList list = new ArrayList();
for(int i = 0;i < 10000;i++) {
list.add(primeStart);
primeStart = getNextPrime(primeStart);
}
}

如果我像这样运行代码,大约需要 56 秒。但是,如果我有以下代码(作为替代):

public class PrimeRunnable implements Runnable {

private int from;
private int lastPrime;

public PrimeRunnable(int from) {
this.from = from;
}

public boolean isPrime(int number) {
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return false;
}
}
lastPrime = number;
return true;
}

public int getLastPrime() {
return lastPrime;
}

public void run() {
while(!isPrime(++from))
;
}
}

public static void main(String[] args) {
int primeStart = 5;
ArrayList list = new ArrayList();
for(int i = 0;i < 10000;i++) {
PrimeRunnable pr = new PrimeRunnable(primeStart);
Thread t = new Thread(pr);
t.start();
t.join();
primeStart = pr.getLastPrime();
list.add(primeStart);
}
}

整个操作大约需要 7 秒。我几乎可以肯定,即使我一次只创建一个线程,一个线程并不总是在创建另一个线程时完成。是对的吗?我也很好奇:为什么行动这么快就结束了?

当我加入一个线程时,其他线程是否继续在后台运行,还是只有加入的线程在运行?

最佳答案

通过将 join() 放入循环中,您将启动一个线程,然后等待该线程停止,然后再运行下一个线程。我认为您可能想要更像这样的东西:

public static void main(String[] args) {
int primeStart = 5;

// Make thread-safe list for adding results to
List list = Collections.synchronizedList(new ArrayList());

// Pull thread pool count out into a value so you can easily change it
int threadCount = 10000;
Thread[] threads = new Thread[threadCount];

// Start all threads
for(int i = 0;i < threadCount;i++) {
// Pass list to each Runnable here
// Also, I added +i here as I think the intention is
// to test 10000 possible numbers>5 for primeness -
// was testing 5 in all loops
PrimeRunnable pr = new PrimeRunnable(primeStart+i, list);
Thread[i] threads = new Thread(pr);
threads[i].start(); // thread is now running in parallel
}

// All threads now running in parallel

// Then wait for all threads to complete
for(int i=0; i<threadCount; i++) {
threads[i].join();
}
}

顺便说一下,如果没有素数,pr.getLastPrime() 将返回 0,因此您可能希望在将其添加到列表之前将其过滤掉。 PrimeRunnable 必须承担添加到最终结果列表的工作。另外,我认为 PrimeRunnable 实际上被破坏了,因为它仍然有递增的代码。我认为这是固定的,但我实际上并没有编译它。

public class PrimeRunnable implements Runnable {    
private int from;
private List results; // shared but thread-safe

public PrimeRunnable(int from, List results) {
this.from = from;
this.results = results;
}

public void isPrime(int number) {
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return;
}
}
// found prime, add to shared results
this.results.add(number);
}

public void run() {
isPrime(from); // don't increment, just check one number
}
}

并行运行 10000 个线程不是一个好主意。创建一个大小合理的固定线程池并让它们从共享队列中提取工作是一个更好的主意。基本上每个工作人员都从同一个队列中提取任务,处理它们并将结果保存在某个地方。与 Java 5+ 最接近的端口是使用由线程池支持的 ExecutorService。您还可以使用将 ExecutorService 与结果队列组合在一起的 CompletionService。

ExecutorService 版本看起来像:

public static void main(String[] args) {
int primeStart = 5;

// Make thread-safe list for adding results to
List list = Collections.synchronizedList(new ArrayList());

int threadCount = 16; // Experiment with this to find best on your machine
ExecutorService exec = Executors.newFixedThreadPool(threadCount);

int workCount = 10000; // See how # of work is now separate from # of threads?
for(int i = 0;i < workCount;i++) {
// submit work to the svc for execution across the thread pool
exec.execute(new PrimeRunnable(primeStart+i, list));
}

// Wait for all tasks to be done or timeout to go off
exec.awaitTermination(1, TimeUnit.DAYS);
}

希望这给了你一些想法。我希望最后一个例子看起来比第一个好很多。

关于java - 代码性能比较,线程与非线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/248405/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com