我有一个相当大的ArrayList。
我必须仔细检查每个索引,并进行昂贵的计算
我加速它的第一个想法是将其放入线程中。 它可以工作,但是仍然非常慢。我对计算进行了修改,以使其更便宜,但仍然很慢。我想出的最好的解决方案基本上就是这个。
if(isset($_POST['btnLogin']))
{
$username = $_POST['txtusername'];
$pass_word = $_POST['txtpassword'];
$hashed_password = crypt(sha1($pass_word));
$sqlQuery = "SELECT * from users WHERE username = :username AND password = :password" ;
$statement = $conn->prepare($sqlQuery);
$statement->execute(array(':username' =>$user , ':password'=>$hashed_password));
while($row = $statement->fetch_object())
{
$id = $row->id;
$username = $row->username;
$password = $row->password;
if(strcmp('$password', '$hashed_password') == 0)
{
echo '<script type="text/javascript">console.log("Success");</script>';
}
else
{
echo '<script type="text/javascript">console.log("Failed");</script>';
}
}
但是,这感觉像是一个懒惰,不专业的解决方案。这就是为什么我要问是否有更清洁,甚至更快的解决方案
答案 0 :(得分:2)
从理论上讲很高: 如果您有X个元素,并且您的计算必须对每个元素执行N次运算,则 您的计算机(处理器)必须总共执行X * N次操作,然后...
只有在计算操作中有一些线程正在等待时,并行线程才能使其速度更快(例如,文件或网络操作)。该时间可以由其他线程使用。但是,如果所有操作都是纯CPU(例如数学)并且线程没有等待-执行X * N操作所需的时间保持不变。
每个踏步还必须在某些时候赋予其他线程控制CPU的能力。它会在方法调用之间自动执行,或者在代码中调用Thread.yield()
时自动发生。
作为示例方法,例如:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
在完全完成并退出之前,不会给其他线程控制CPU的机会。
答案 1 :(得分:0)
假设在每个元素上执行任务不会导致数据争用,则可以利用并行功能。为了最大化同时进行的计算数量,您必须将任务分配给系统中可用的每个处理器。
在Java中,您可以使用以下方法获得可用的处理器(核心)数量:
int parallelism = Runtime.getRuntime().availableProcessors();
想法是创建等于可用处理器的线程数。
因此,如果有4个处理器可用,则可以创建4个线程,并要求它们以4的间隔进行处理。假设您有一个大小为10的列表,需要并行处理。
然后
线程1处理索引为0、4、8的项目
线程2处理索引为1,5,9的项目
线程3处理索引为2,6的项目
线程4处理索引为3,7的项目
我尝试使用以下代码模拟您的情况:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
输出:
结果:
顺序执行的总时间:50.001秒
使用2个线程执行的总时间:25.102秒
使用4个线程执行的总时间:15.002秒