java并发编程

214 阅读3分钟

大纲

image.png

概览

进程与线程

java线程

常见方法

image.png

image.png

image.png

start和run

run

image.png

start

image.png

小结

  • 直接调用 run 是在主线程中执行了 run,没有启动新的线程
  • 使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码

sleep 与 yield

image.png

image.png

限制对cpu的使用

sleep

image.png

image.png

  • 此处利用linux,分配了一核cpu,直接while(true)才可以模拟出100%
  • 多核的话,模拟不出来
  • 加上sleep,cpu占用从100%降低到5%,效果明显;

image.png

join

为什么需要join

image.png

image.png

应用之同步

以调用方角度来讲,如果

  • 需要等待结果返回,才能继续运行就是同步
  • 不需要等待结果返回,就能继续运行就是异步

image.png

等待多个线程结果

image.png

image.png

image.png

有时效的 join

image.png

  • 如果join(2s),线程只需要1s执行完,则主线程1s后继续执行
  • 如果join(2s),线程需要3s执行完,则主线程最多等到2s后继续执行

interrupt

打断 sleep,wait,join 的线程

这几个方法都会让线程进入阻塞状态 打断 sleep 的线程, 会清空打断状态,以 sleep 为例

image.png

打断正常运行的线程

image.png

模式之两阶段终止

错误思路

image.png

两阶段终止

image.png

image.png

image.png

打断 park

image.png

image.png

不推荐使用的方法

image.png

守护线程

image.png

image.png

五种状态

操作系统层面出发 image.png

image.png

六种状态

这是从 Java API 层面来描述的

根据 Thread.State 枚举,分为六种状态

image.png

image.png

代码


@Slf4j(topic = "c.TestState")
public class TestState {
    public static void main(String[] args) throws IOException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug("running...");
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                while(true) { // runnable

                }
            }
        };
        t2.start();

        Thread t3 = new Thread("t3") {
            @Override
            public void run() {
                log.debug("running...");
            }
        };
        t3.start();

        Thread t4 = new Thread("t4") {
            @Override
            public void run() {
                synchronized (TestState.class) {
                    try {
                        Thread.sleep(1000000); // timed_waiting
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t4.start();

        Thread t5 = new Thread("t5") {
            @Override
            public void run() {
                try {
                    t2.join(); // waiting
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t5.start();

        Thread t6 = new Thread("t6") {
            @Override
            public void run() {
                synchronized (TestState.class) { // blocked
                    try {
                        Thread.sleep(1000000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t6.start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // new
        log.debug("t1 state {}", t1.getState());
        // runnable
        log.debug("t2 state {}", t2.getState());
        // TERMINATED
        log.debug("t3 state {}", t3.getState());
        // TIMED_WAITING
        log.debug("t4 state {}", t4.getState());
        // WAITING
        log.debug("t5 state {}", t5.getState());
        // BLOCKED
        log.debug("t6 state {}", t6.getState());
        System.in.read();
    }
}

结果:

17:30:07.220 c.TestState [t3] - running...
17:30:07.723 c.TestState [main] - t1 state NEW
17:30:07.725 c.TestState [main] - t2 state RUNNABLE
17:30:07.725 c.TestState [main] - t3 state TERMINATED
17:30:07.725 c.TestState [main] - t4 state TIMED_WAITING
17:30:07.725 c.TestState [main] - t5 state WAITING
17:30:07.725 c.TestState [main] - t6 state BLOCKED

总结

image.png

应用之统筹(烧水泡茶)

image.png

join


@Slf4j(topic = "c.Test16")
public class Test16 {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            log.debug("洗水壶");
            sleep(1);
            log.debug("烧开水");
            sleep(5);
        },"老王");

        Thread t2 = new Thread(() -> {
            log.debug("洗茶壶");
            sleep(1);
            log.debug("洗茶杯");
            sleep(2);
            log.debug("拿茶叶");
            sleep(1);
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("泡茶");
        },"小王");

        t1.start();
        t2.start();
    }
}

结果:

17:48:20.594 c.Test16 [老王] - 洗水壶
17:48:20.594 c.Test16 [小王] - 洗茶壶
17:48:21.602 c.Test16 [小王] - 洗茶杯
17:48:21.602 c.Test16 [老王] - 烧开水
17:48:23.607 c.Test16 [小王] - 拿茶叶
17:48:26.607 c.Test16 [小王] - 泡茶

Process finished with exit code 0

共享模型之管程

juejin.cn/post/711279…

并发之共享模型

管程-悲观锁(阻塞)

JMM

无锁-乐观锁(非阻塞)

不可变

本章内容

  • 不可变类使用
  • 不可变类设计
  • 无状态类设计

日期转化的问题

image.png

image.png

同步加锁

image.png

不可变类

image.png

image.png

不可变类设计

final使用

image.png

保护性拷贝

image.png

image.png

image.png

享元模式

juejin.cn/post/711064…

无状态设计

image.png

并发工具

image.png

见:juejin.cn/post/711083…

异步编程

并发之非共享模型

参考视频

www.bilibili.com/video/BV16J…