异步编程学习之路(一)-通过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实现线程安全的多线程

猜你喜欢

转载自blog.csdn.net/qq_19734597/article/details/85051309