3

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

 1 year ago
source link: https://blog.51cto.com/jackwei/5881745
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

精选 原创

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

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

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

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());
        }
    }
}

可以看到启动一个类,就有如下几个线程启动了:

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

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

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

真的,Java并发编程入门看这个就够了_java_03
真的,Java并发编程入门看这个就够了_多线程_04
上面已经给出了实例了。

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接口方式");
    }
}

2.2 Thread和Runnable的区别

通过上面的代码演示可以知道,线程最主要的就是Thread类Runnable接口
那他们直接的关系和区别又是什么呢?
Thread类:Java世界一切皆对象,所以对线程的抽象就是Thread类了。
Runnable接口:线程已经有抽象了,而且看接口的源码只有一个run方法,可知他是对任务的抽象,将你想并行执行的任务放到run里面即可。

真的,Java并发编程入门看这个就够了_ide_05
如果在网上看到有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...");
    }
}

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();
    }
}

4. 守护线程

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

Thread thread = new Thread();
thread.setDaemon(true);

5. 优先级

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

6. 线程生命周期

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

真的,Java并发编程入门看这个就够了_并发编程_06

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

  • 1收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK