• 真的,Java并发编程基础入门看这个就够了


    Java并发编程学习之02Java并发编程入门指南

    在这里插入图片描述

    1. Java天生多线程

    import java.lang.management.ManagementFactory;
    import java.lang.management.ThreadInfo;
    import java.lang.management.ThreadMXBean;
    
    public class JavaThread {
        public static void main(String[] args) {
            // Java 虚拟机线程管理接口
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            // 线程和线程堆栈信息
            ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
            // 打印信息
            for (ThreadInfo threadInfo : threadInfos) {
                System.out.println("[" + threadInfo.getThreadId() + "]" + " " + threadInfo.getThreadName());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    可以看到启动一个类,就有如下几个线程启动了:
    在这里插入图片描述

    2. Java启动多线程实现方式

    这里总结了一下Java启动多线程的方式。
    我们先去java.lang.Thread类里面一探究竟,可以看到下面的注释。
    源码里面说一般有两种方法可以创建新的执行线程。

    在这里插入图片描述
    在这里插入图片描述
    上面已经给出了实例了。

    2.1 实现代码

    根据官方文档的提示,我们的两种实现线程的方式如下:

    public class JavaThreadDemo {
        public static void main(String[] args) {
            // 创建第一种方式对象
            PrimeThread p1 = new PrimeThread(143);
            // 启动线程
            p1.start();
    
            // 创建第二种方式
            PrimeRun p2 = new PrimeRun(143);
            // 注意这里作为参数
            new Thread(p2).start();
        }
    }
    
    /**
     * 第一种方式:继承Thread类
     */
    class PrimeThread extends Thread {
        long minPrime;
    
        PrimeThread(long minPrime) {
            this.minPrime = minPrime;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "===我是继承Thread类实现方式");
        }
    }
    
    /**
     * 第二种方式:实现Runnable接口
     */
    class PrimeRun implements Runnable {
        long minPrime;
    
        PrimeRun(long minPrime) {
            this.minPrime = minPrime;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "===我是实现Runnable接口方式");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    2.2 Thread和Runnable的区别

    通过上面的代码演示可以知道,线程最主要的就是Thread类Runnable接口
    那他们直接的关系和区别又是什么呢?
    Thread类:Java世界一切皆对象,所以对线程的抽象就是Thread类了。
    Runnable接口:线程已经有抽象了,而且看接口的源码只有一个run方法,可知他是对任务的抽象,将你想并行执行的任务放到run里面即可。
    在这里插入图片描述
    如果在网上看到有N中实现方式,其实就是在这两个基础上衍生出来的。

    2.3 start和run方法的区别

    start() 是启动线程去执行,所以不管创建多线程那种方式都要用start启动。
    run() 只是方法执行,并不会新建线程。

    import org.junit.Test;
    
    public class StartRunThread {
        /**
         * 1. 测试启动两次
         */
        @Test
        public void test1() {
            MyThread myThread = new MyThread();
            myThread.start();
            // 第二次调用会抛出异常:IllegalThreadStateException
            myThread.start();
        }
    
        /**
         * 2. 测试run方法
         * 可以看到,run调用就是普通的方法调用,并没有启动线程去执行
         */
        @Test
        public void test2() {
            MyThread myThread = new MyThread();
            myThread.run();
            myThread.run();
        }
    }
    class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println(Thread.currentThread().getName() + " while running...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    3. Java如何停止线程呢

    有了开始一定会有终止,就像人生一样~

    3.1 已弃用方法

    方法名说明
    stop从1.2版本就已经弃用了,会立即停止线程造成不安全,做到一半就停了会导致资源不会正常释放
    suspend从1.2版本就已经弃用了,挂起线程。它天生就容易死锁。如果目标线程在监视器上持有锁,在关键系统资源被挂起时保护该资源,则在目标线程恢复之前,没有线程可以访问该资源。如果将恢复目标线程的线程试图在调用Resume之前锁定此监视器,则会导致死锁。这种死锁通常表现为“冻结”的进程。
    resume从1.2版本就已经弃用了,恢复挂起线程,和suspend配合使用,容易导致死锁

    为什么要弃用stop呢?
    可以参考官方文档:
    https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

    3.2 推荐使用

    方法名说明
    interrupt使得线程作为协作,对另一个线程进行中断请求,当线程处理好身后事(比如释放资源)再停止。interrupted判断线程是否被中断。静态类的isInterrupted 判断线程是否被中断,并清除标志位为false
    import org.junit.Test;
    
    public class JavaThreadStopDemo {
        static class StopThread2 extends Thread {
            @Override
            public void run() {
                // 输出中断标识位
                System.out.println(Thread.currentThread().getName() + " start interrupt flag === " + this.isInterrupted());
                // 判断是否有中断请求
                while (!this.isInterrupted()) {
                    // 输出中断标识位
                    System.out.println(Thread.currentThread().getName() + " while interrupt flag === " + this.isInterrupted());
                }
                // 输出中断标识位:Thread-0 end interrupt flag === true
                System.out.println(Thread.currentThread().getName() + " end interrupt flag === " + this.isInterrupted());
            }
        }
    
        @Test
        public void testStop2() throws InterruptedException {
            StopThread2 stop2 = new StopThread2();
            stop2.start();
            // 延迟指定毫秒,可调节
            Thread.sleep(8);
            stop2.interrupt();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    4. 守护线程

    主线程执行完之后守护线程也会自动消亡。
    必须要在start之前设置,如果有finally也不一定执行!

    Thread thread = new Thread();
    thread.setDaemon(true);
    
    • 1
    • 2

    5. 优先级

    取值1~10直接,作用不大。

    6. 线程生命周期

    线程的生命周期分为:新建、就绪、运行、阻塞、消亡,五个状态。

    在这里插入图片描述

    代码仓

    以上全部的代码:
    https://gitee.com/jack0240/spring-cloud-demo.git
    在这里查看哟~

  • 相关阅读:
    采用一种估值方法,自动化评估某个股票价格合理性
    软考复习 -- 计算机网络
    【自动化测试】如何在jenkins中搭建allure
    Three.js 实现简单的PCD加载器(可从本地读取pcd文件)【附完整代码】
    css 自定义虚线
    element的el-select给下拉框添加背景
    MFC Windows 程序设计[215]之精美登录框的实现(附源码)
    国产1.8V低电压输入,可用于驱动步进电机;H 桥驱动电路单元可以直接驱动IR-CUT
    SQL Server - 使用 Merge 语句实现表数据之间的对比同步
    目标检测如何演变:从区域提议和 Haar 级联到零样本技术
  • 原文地址:https://blog.csdn.net/WeiHao0240/article/details/127876210