1. 程式人生 > >非同步程式設計學習之路(一)-通過Thread實現簡單多執行緒

非同步程式設計學習之路(一)-通過Thread實現簡單多執行緒

自上週主管帶我看過kafka內部實現,使用Feature來做的資料批量傳送之後,自此決定要學好併發程式設計。

因為本人在多執行緒上只能說是一個新手,打算從最底層的Thread一步一步記錄我的學習之路。

通過Thread實現多執行緒的方式有兩種,程式碼如下:

一、多執行緒實現(繼承Thread類)

/**
 * @Description:簡單多執行緒的實現(執行緒不安全)
 * @Author:zhangzhixiang
 * @CreateDate:2018/12/21 20:30:54
 * @Version:1.0
 */
public class TestThread extends Thread {
    
    @Override
    public void run() {
        for (int i = 0; i<10000;i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        TestThread thread = new TestThread();
        thread.start();
    }
}

執行結果:

0
1
2
.
.
9999

二、多執行緒實現(實現Runnable介面)

1、Runnable實現類

/**
 * @Description:簡單多執行緒的實現(執行緒不安全)
 * @Author:zhangzhixiang
 * @CreateDate:2018/12/21 20:30:54
 * @Version:1.0
 */
public class RunnalbeImpl implements Runnable {

    @Override
    public void run() {
        for(int i = 0; i<10000; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        RunnableImpl runnable = new RunnableImpl();
        new Thread(runnable).start();
    }
}

執行結果:同上 

上面是第一種runnable寫法,另一種可以通過JDK8的lambda表示式來寫,程式碼如下:

/**
 * @Description:簡單多執行緒的實現(執行緒不安全)
 * @Author:zhangzhixiang
 * @CreateDate:2018/12/21 20:30:54
 * @Version:1.0
 */
public class TestThread {

    public static void main(String[] args) {
        Count count = new Count();
        Runnable runnable = () -> {
            for (int i = 0; i < 10000; i++) {
                count.increment();
            }
        };
        List<Thread> threads = new ArrayList<>(10);
        for (int i=0; i < 10; i++) {
            Thread thread = new Thread(runnable);
            threads.add(thread);
            thread.start();
        }
        while(true) {
            if(isAllThreadDead(threads)) {//所有執行緒執行結束
                System.out.println(count.get());
                break;
            }
        }
    }

    private static boolean isAllThreadDead(List<Thread> threads) {
        for (Thread thread : threads) {
            if(thread.isAlive()) {
                return false;
            }
        }
        return true;
    }
}

2、Count計數類

/**
 * @Description:Count計數類
 * @Author:zhangzhixiang
 * @CreateDate:2018/12/21 20:38:54
 * @Version:1.0
 */
public class Count {
    
    private int num;
    
    public void increment() {
        num++;
    }

    public int get() {
        return num;
    }
}

執行結果:

91561

上面的示例都是執行緒不安全的,從第三個示例可以看出執行緒不安全這一點,示例中同時運行了10個執行緒,並且每個執行緒迴圈10000次每次自增1,按正常的邏輯,返回的結果應該是10萬,但實際執行結果是91561,為什麼呢??原因是因為多執行緒具有三種特性,分別是原子性、可見性、有序性。而這裡count物件對於10個執行緒來說是共享資源,由於這10個執行緒發生了併發,每次取到的數值有可能不是其他執行緒計算完後得到的count,這就會造成最後結果不是10萬而是一個不準確的值。

如何實現執行緒安全的多執行緒呢?請見下一篇文章:

非同步程式設計學習之路(二)-通過Synchronize實現執行緒安全的多執行緒