多线程面试题系列1_数组多线程分解
多线程优势:
在i7-8550U CPU平台比单线程快2-4倍以上题目:
(假设多线程数为N)给定N个数组,每个数组中存着DATASIZE = 15000000个数字,为每个数组中的每个数字单独判断一次是否为素数。
多线程与单线程元素均采用单独素数判断时效率极高的相邻剪枝法(在我另一篇文章中有写),比较之间的差距。
这里假设N为16,为每个数组填充值为1到15000000的元素。需要注意的点:
在最后归并时需要对同一个对象加锁synchronized,以防static变量更新错误。
package com.company;
class Sun implements Runnable {
private static int THREADLINES;
private static int DATASIZE;
public static int answer;
private int[][] data;
private Thread[] thread;
Sun(final int DATASIZE, final int THREADLINES) {
this.DATASIZE = DATASIZE; this.THREADLINES = THREADLINES;
data = new int[THREADLINES][]; thread = new Thread[THREADLINES];
for(int i = 0; i < THREADLINES; i++) {
data[i] = new int[DATASIZE];
for(int j = 0; j < DATASIZE; j++) {
data[i][j] = j + 1;
}
}
for(int i = 0; i < THREADLINES; i++) thread[i] = new Thread(this);
}
void stage() {
for(Thread e : thread) e.start();
}
boolean isPrimeNumber(int n)
{
if(n == 2 || n == 3)
return true;
if(n % 6 != 1 && n % 6 != 5)
return false;
for(int i = 5; i <= Math.sqrt(n); i+=6)
{
if(n % i == 0 || n % (i+2) == 0)
return false;
}
return true;
}
void getPrimeNumber(int index) {
int cache = 0;
for(int i = 0; i < DATASIZE; i++) {
if(isPrimeNumber(data[index][i]))
cache ++;
}
synchronized(this) {
answer += cache;
}
}
public void run() {
if(Thread.currentThread() == thread[0]) {
getPrimeNumber(0);
} else if(Thread.currentThread() == thread[1]) {
getPrimeNumber(1);
} else if(Thread.currentThread() == thread[2]) {
getPrimeNumber(2);
} else if(Thread.currentThread() == thread[3]) {
getPrimeNumber(3);
} else if(Thread.currentThread() == thread[4]) {
getPrimeNumber(4);
} else if(Thread.currentThread() == thread[5]) {
getPrimeNumber(5);
} else if(Thread.currentThread() == thread[6]) {
getPrimeNumber(6);
} else if(Thread.currentThread() == thread[7]) {
getPrimeNumber(7);
} else if(Thread.currentThread() == thread[8]) {
getPrimeNumber(8);
} else if(Thread.currentThread() == thread[9]) {
getPrimeNumber(9);
} else if(Thread.currentThread() == thread[10]) {
getPrimeNumber(10);
} else if(Thread.currentThread() == thread[11]) {
getPrimeNumber(11);
} else if(Thread.currentThread() == thread[12]) {
getPrimeNumber(12);
} else if(Thread.currentThread() == thread[13]) {
getPrimeNumber(13);
} else if(Thread.currentThread() == thread[14]) {
getPrimeNumber(14);
} else if(Thread.currentThread() == thread[15]) {
getPrimeNumber(15);
}
}
}
public class Method {
private static final int DATASIZE = 15000000;
private static final int THREADLINES = 16;
static boolean isPrimeNumber(int n)
{
if(n == 2 || n == 3)
return true;
if(n % 6 != 1 && n % 6 != 5)
return false;
for(int i = 5; i <= Math.sqrt(n); i+=6)
{
if(n % i == 0 || n % (i+2) == 0)
return false;
}
return true;
}
public static void main(String[] args) {
int[][] data = new int[THREADLINES][DATASIZE];
for(int i = 0; i < THREADLINES; i++) {
for(int j = 0; j < DATASIZE; j++) {
data[i][j] = j + 1;
}
}
// 传统方法
long start = System.currentTimeMillis();
int sum = 0;
for(int i = 0; i < THREADLINES; i++) {
for(int j = 0; j < DATASIZE; j++)
if(isPrimeNumber(data[i][j])) sum ++;
}
System.out.println("单线程:\t" + sum + "\t耗时 " + (System.currentTimeMillis() - start) / 1000.0
+ "秒");
// 多线程
start = System.currentTimeMillis();
Sun sun = new Sun(DATASIZE, THREADLINES);
sun.stage();
while(true) {
if(Thread.activeCount() == 2) {
System.out.println("多线程:\t" + sun.answer + "\t耗时 " + (System.currentTimeMillis() - start) / 1000.0
+ "秒");
break;
}
}
}
}
运行结果: