我已经成功地使用了两个线程来计算阶乘,而没有使用线程池。我有两个阶乘类,它们分别命名为Factorial1和Factorial2,并且都继承自Thread类。假设我要计算的是!160000,那么在Factorial1的run()方法中,我使用for循环从i=2到i=80000进行乘法操作;在Factorial2的run()方法中,我使用for循环从i=80001到i=160000进行乘法操作。之后,我将这两个值返回并在主方法中将它们相乘。当我比较执行时间时,用两个线程来计算阶乘明显更快(只需要5000毫秒),即使使用了两个线程也优于不使用线程的计算时间(需要15000毫秒)。
现在我想编写更加清晰和高效的代码,因为我看到了线程在阶乘计算中的效率。但是,当我使用线程池来计算阶乘时,与非线程计算相比,并行计算总是需要更多的时间(近16000毫秒)。我的代码片段如下:
在我看来,这个锁可能会破坏线程使用的所有优势,因为它似乎只是在做乘法,没有其他任何操作。但如果没有它,我甚至不能计算出真正的结果。比如说我想计算!10,那么thread1就要计算10*9*8*7*6,而thread2则要计算5*4*3*2*1。这是我想要的方式吗?使用线程池是否可行?当然,执行时间必须少于普通计算...
非常感谢您提供的所有帮助和建议。
编辑:- 我自己解决问题的方法 -
现在我想编写更加清晰和高效的代码,因为我看到了线程在阶乘计算中的效率。但是,当我使用线程池来计算阶乘时,与非线程计算相比,并行计算总是需要更多的时间(近16000毫秒)。我的代码片段如下:
for(int i=2; i<= Calculate; i++)
{
myPool.execute(new Multiplication(result, i));
}
在Multiplication类中的run()方法:
public void run()
{
s1.Mltply(s2); // s1 and s2 are instances of my Number class
// their fields holds BigInteger values
}
Number类中的Mltply()方法:
public void Multiply(int number)
{
area.lock(); // result is going wrong without lock
Number temp = new Number(number);
value = value.multiply(temp.value); // value is a BigInteger
area.unlock();
}
在我看来,这个锁可能会破坏线程使用的所有优势,因为它似乎只是在做乘法,没有其他任何操作。但如果没有它,我甚至不能计算出真正的结果。比如说我想计算!10,那么thread1就要计算10*9*8*7*6,而thread2则要计算5*4*3*2*1。这是我想要的方式吗?使用线程池是否可行?当然,执行时间必须少于普通计算...
非常感谢您提供的所有帮助和建议。
编辑:- 我自己解决问题的方法 -
public class MyMultiplication implements Runnable
{
public static BigInteger subResult1;
public static BigInteger subResult2;
int thread1StopsAt;
int thread2StopsAt;
long threadId;
static boolean idIsSet=false;
public MyMultiplication(BigInteger n1, int n2) // First Thread
{
MyMultiplication.subResult1 = n1;
this.thread1StopsAt = n2/2;
thread2StopsAt = n2;
}
public MyMultiplication(int n2,BigInteger n1) // Second Thread
{
MyMultiplication.subResult2 = n1;
this.thread2StopsAt = n2;
thread1StopsAt = n2/2;
}
@Override
public void run()
{
if(idIsSet==false)
{
threadId = Thread.currentThread().getId();
idIsSet=true;
}
if(Thread.currentThread().getId() == threadId)
{
for(int i=2; i<=thread1StopsAt; i++)
{
subResult1 = subResult1.multiply(BigInteger.valueOf(i));
}
}
else
{
for(int i=thread1StopsAt+1; i<= thread2StopsAt; i++)
{
subResult2 = subResult2.multiply(BigInteger.valueOf(i));
}
}
}
}
public class JavaApplication3
{
public static void main(String[] args) throws InterruptedException
{
int calculate=160000;
long start = System.nanoTime();
BigInteger num = BigInteger.valueOf(1);
for (int i = 2; i <= calculate; i++)
{
num = num.multiply(BigInteger.valueOf(i));
}
long end = System.nanoTime();
double time = (end-start)/1000000.0;
System.out.println("Without threads: \t" +
String.format("%.2f",time) + " miliseconds");
System.out.println("without threads Result: " + num);
BigInteger num1 = BigInteger.valueOf(1);
BigInteger num2 = BigInteger.valueOf(1);
ExecutorService myPool = Executors.newFixedThreadPool(2);
start = System.nanoTime();
myPool.execute(new MyMultiplication(num1,calculate));
Thread.sleep(100);
myPool.execute(new MyMultiplication(calculate,num2));
myPool.shutdown();
while(!myPool.isTerminated()) {} // waiting threads to end
end = System.nanoTime();
time = (end-start)/1000000.0;
System.out.println("With threads: \t" +String.format("%.2f",time)
+ " miliseconds");
BigInteger result =
MyMultiplication.subResult1.
multiply(MyMultiplication.subResult2);
System.out.println("With threads Result: " + result);
System.out.println(MyMultiplication.subResult1);
System.out.println(MyMultiplication.subResult2);
}
}
输入: !160000 没有使用线程的执行时间: 15000 毫秒 使用 2 个线程的执行时间: 4500 毫秒
感谢您的想法和建议。
Number temp = new Number(number);
我看不到temp被使用过。 - Jhonny007