1. 程式人生 > >java多執行緒使用

java多執行緒使用

首先說一下多執行緒的應用場景吧:
比如:迅雷檔案看一個視訊,我們發現進度條顯示不一樣。一個檔案有些地方可以直接看,而前面時間的視訊還可能不能看。
這時候就是用多執行緒,將一個檔案分成多份進行快取,最後再將分割的視訊進行組裝。

eg:
1+2+3+..+1億;(最開始測試用的是1兆,但是超過了double的範圍,計算的資料不準確,用bigdecimal太麻煩了)
如何快速運算出資料結果 ?

常規演算法:
public static void main(String[] args) {
     long sum = 0L;
     for (long i = 1L; i <= 100000000L; i++) {
         sum += i;
     }
     System.out.println("1到1億累加的和為:" + sum);
}

上面這一段程式碼確實可以計算出資料最後的和: 5000000050000000。
但是呢 ? 速度太慢了。


這時候就可以用多執行緒。
上面的程式碼用的是1個執行緒執行,需要時間大約30毫秒。

如果同時開10個執行緒,時間就會大大縮短近6倍。


先不用執行緒池吧,建立執行緒有3種方式,測試這個必須用第3種方式,因為多執行緒只有Callable<T>有返回值:


多執行緒演算法:
1. 先建立一個多執行緒執行的類
public class Sum implements Callable<List> {

    private long min;
    private long max;

    public Sum(long min, long max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public List call() throws Exception {
        long l = System.currentTimeMillis();
        long sum = 0;
        for (long i = min; i <= max; i++) {
            sum += i;
        }
        long e = System.currentTimeMillis();
        long time = e - l;
        // 將求和資料 與 求和時間 封裝到list集合。
        ArrayList arrayList = new ArrayList();
        arrayList.add(sum);
        arrayList.add(time);
        System.out.println("sum = " + sum);
        return arrayList;
    }
}

2. 建立10個多執行緒
public class TestOne {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 建立帶有10個執行緒的執行緒池
        ExecutorService pool = Executors.newFixedThreadPool(10);

        long max = 100000000L;
        int d = 10; // 建立10個執行緒
        assert max >d; // 斷言,等同於這個意思: if (max <= d) throw new AssertionError();
        long sp = max /10;
        List<Future<List>> fs = new ArrayList<>();
        for (int i = 1; i <= d; i++) {
            if (i < d) {
                fs.add(pool.submit(new Sum(1 + (i - 1) * sp, i * sp)));
            } else {
                fs.add(pool.submit(new Sum(1 + (i - 1) * sp, max)));
            }
        }

        long s = 0, t = 0;
        for (Future<List> f : fs) {
            List list = f.get();
            s += (long) list.get(0);
            t += (long) list.get(1);
        }

        pool.shutdown();
        // 這個時間不是很準確,但是計算時間,確實比單執行緒更快
        System.out.println("求和:" + s + ",求和時間:" + t/d);
    }
}