Java并发编程基础

155 阅读2分钟

了解并发编程

并发编程是Java程序员最重要的技能之一,也是最难掌握的技能之一。很多情况下我们不敢轻易使用,因为不了解其底层原理,很可能踩坑。接下来一段时间就来学习并发编程的底层类源码。
本篇先了解并发编程的基础。

上图是从并发编程的艺术书中摘录。简单解释一下。
当调用Thread.start后,线程进入可运行状态。只等cpu分配时间片啦。
yield()方法后,线程可让出自己,让其他线程先执行,该线程仍可以随时执行。
wait()方法后进入等待状态。让出自己的资源。
当线程synchronized没有获得锁,则进入阻塞状态。
线程执行完成后,进入终止状态。

下面一起来看start方法和wait、notify方法的使用

public class MultiThreadBase {

    private static Object res = new Object();
    public static void main(String[] args) throws InterruptedException {
        final MultiThreadBase multiThreadBase = new MultiThreadBase();

        for(int i=0; i< 5; i++) {
            new Thread(()-> {
                multiThreadBase.testWait();
            }).start();
        }
        TimeUnit.SECONDS.sleep(1L);
        System.out.println("---多线程已启动---");
        synchronized (res) {
            res.notify();
        }
        TimeUnit.SECONDS.sleep(1L);
        System.out.println("---一个线程已被唤醒---");
        synchronized (res) {
            res.notifyAll();
        }
        TimeUnit.SECONDS.sleep(1L);
        System.out.println("---全部等待线程已被唤醒---");
    }

    private void testWait() {
        synchronized (res) {
            System.out.println(Thread.currentThread().getName() + ": start");
            try {
                res.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ": end");
        }
    }
}

运行结果:

Thread-0: start
Thread-2: start
Thread-1: start
Thread-3: start
Thread-4: start
---多线程已启动---
Thread-0: end
---一个线程已被唤醒---
Thread-4: end
Thread-3: end
Thread-1: end
Thread-2: end
---全部等待线程已被唤醒---

上面代码可以看到

  • wait方法使用时应先加锁
  • wait方法会释放锁资源(注意这是和Thread.sleep方法不同的)
  • notify方法唤醒一个等待该资源的线程
  • notifyAll方法唤醒所有等待该资源的线程
private static void testJoin(MultiThreadBase multiThreadBase) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " testJoin start");
        Thread t = new Thread(()-> {
            System.out.println(Thread.currentThread().getName() + " start");
            try {
                TimeUnit.SECONDS.sleep(2L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end");
        });
        t.start();
        t.join();
        System.out.println(Thread.currentThread().getName() + " testJoin end");
    }

运行结果:

main testJoin start
Thread-0 start
Thread-0 end
main testJoin end

可以看到当使用join方法后,当前线程会等待目标线程执行完后,才执行后续代码(有兴趣的朋友可以看join方法源码,内部确实是调用wait方法)

并发编程基础方法先介绍到这,下一篇介绍interrupt方法,水平有限,说的不对的地方请大家指出,及时修正