Under my umbrella.

SKII

Less is more.

多线程面试题系列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;
            }
        }
    }
}

运行结果:

posted @ 2019-10-28 21:39  NLYang  阅读(358)  评论(0编辑  收藏  举报