Java 线程与非线程代码性能的比较
假设以下代码,我有一些与线程相关的问题。请忽略代码可能的低效性,我只对线程部分感兴趣Java 线程与非线程代码性能的比较,java,multithreading,concurrency,Java,Multithreading,Concurrency,假设以下代码,我有一些与线程相关的问题。请忽略代码可能的低效性,我只对线程部分感兴趣 //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
//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秒。但是,如果我有以下代码(作为替代):
整个操作大约需要7秒钟。我几乎可以肯定,即使我一次只创建一个线程,但当创建另一个线程时,一个线程并不总是完成。是这样吗?我也很好奇:为什么手术结束得这么快
当我加入一个线程时,其他线程是否仍在后台运行,或者加入的线程是唯一正在运行的线程?请仔细阅读您的代码。这两个案例做的不是同一件事,它与线程无关
当您加入一个线程时,其他线程将在后台运行,是的。运行测试时,第二个线程似乎不需要9秒——事实上,它至少需要与第一个线程一样长的时间(这是意料之中的,threding无助于在您的示例中实现它 Thread.join将仅在Thread.join终止时返回,然后当前线程将继续,您调用join的线程将失效
作为快速参考--在开始一次迭代时考虑线程化不依赖于前一次迭代的结果。您可以通过让第一个示例中的确切代码与线程一起运行来更好地测试这一点。使用以下内容替代主方法:
private static int currentPrime;
public static void main(String[] args) throws InterruptedException {
for (currentPrime = 0; currentPrime < 10000; currentPrime++) {
Thread t = new Thread(new Runnable() {
public void run() {
getNextPrime(currentPrime);
}});
t.run();
t.join();
}
}
私有静态int currentPrime;
公共静态void main(字符串[]args)引发InterruptedException{
用于(currentPrime=0;currentPrime<10000;currentPrime++){
线程t=新线程(新的可运行线程(){
公开募捐{
GetNextTime(currentPrime);
}});
t、 run();
t、 join();
}
}
这将与原始版本在同一时间运行
回答您的“加入”问题:是的,当您使用“加入”时,其他线程可以在后台运行,但在这种特殊情况下,您一次只能有一个活动线程,因为您正在阻止创建新线程,直到最后一个线程完成执行。JesperE是正确的,但我不相信只给出提示(至少在教室外): 请注意非线程版本中的此循环:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
}
}
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return false;
}
}
for(int i=2;i
与此相反,在螺纹版本中:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
}
}
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return false;
}
}
for(int i=2;i
第一个循环将始终完全运行,而第二个循环如果找到除数,将提前退出
您可以通过添加如下break语句使第一个循环提前退出:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
break;
}
}
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();
}
}
for(int i=2;i
通过将join()放入循环中,您正在启动一个线程,然后等待该线程停止,然后再运行下一个线程。我认为您可能需要类似以下内容:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
break;
}
}
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();
}
}
publicstaticvoidmain(字符串[]args){
int primeStart=5;
//创建线程安全列表以将结果添加到
List List=Collections.synchronizedList(新的ArrayList());
//将线程池计数提取到一个值中,以便轻松更改它
int threadCount=10000;
线程[]线程=新线程[threadCount];
//启动所有线程
对于(int i=0;i 对于(int i=0;我在我的笔记本电脑上尝试了这两种方法。我在帖子中写的次数就是我得到的次数。也许是关于我们的虚拟机如何以不同的方式处理事情的。可能是你的thread.join被破坏了,这可以解释运行时的差异……另外,第二种方法抛出了一个你没有处理的异常。我不确定你是如何运行它的。VM你在用什么?你能告诉我“这两个案例做的不是同一件事”是什么意思吗?其中一个案例慢得多的原因是它做的不是同一件事。提示:你调用isPrime()和GetNextTime()的次数是多少分别?如果我将创建的线程添加到一个列表中,然后在退出循环后加入它们呢?如果我这样做,我会有10000个线程同时运行吗?好的,我编写的示例有一个静态int,它在循环中被操纵,所以你需要做一些修改才能工作。但是,如果您使代码线程安全,您可以将这些线程排队并在需要时同时运行它们。但是,对于大量线程,您应该查看java.util.concurrent.ThreadPoolExecutor,而不是尝试一次性执行所有线程。