栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程

目录

线程和方法调用栈的关系

线程中最常见的属性

1.id

2.name

3.在Java代码中看到的线程状态

4.前台线程与后台线程/精灵线程(daemon)/守护线程

JDK中自带的观察线程的工具

TimeUnit.SECONDS.sleep()

Thread.join()方法

Thread常用的几个静态方法

1.Thread.sleep()

2.Thread.current()

线程内容总结

栈和栈帧


线程和方法调用栈的关系

每个线程都有自己独立的调用栈

由于每个线程都是独立的执行流,A在调用过哪些方法,和B根本没关系。表现为每个线程都有自己的独立的栈

调用的是用一个方法:说明执行的是同一批指令

栈不同(帧不同):说明执行指令时,要处理的数据是不同

线程中最常见的属性

1.id

本进程(JVM进程)内部分配的唯一的id只能get不能set

public class Main {
    static class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println(this.getId());
        }
    }
    public static void main(String[] args) {
       Thread thread=  Thread.currentThread();//当前线程
        System.out.println(thread.getId());//主线程id

        MyThread t1=new MyThread();
        t1.start();
        MyThread t2=new MyThread();
        t2.start();
    }
}

启动几个线程就有几个id,不会重复

2.name

默认情况下,主线程默认为main,如果没有给过名字,线程名字遵守Thread-……;第一个是Thread-0,Thread-1……

可以get也可以set

public class Main2 {
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(this.getName());
        }
    }

    public static void main(String[] args) {
//        Thread thread = Thread.currentThread(); // 当前线程
//        System.out.println(thread.getName());
//
        MyThread t1 = new MyThread();
        t1.start();

        MyThread t2 = new MyThread();
        t2.start();

        MyThread t3 = new MyThread();
        t3.start();
    }
}

可以通过setName()设置,也可以通过Thread()构造方法设置

public class Main3 {
    static class MyThread extends Thread {
                public MyThread() {
            setName("我是m");
        }
//        public MyThread() {
//            super("mm");  // 调用父类(Thread)的构造方法
//        }

        @Override
        public void run() {
            System.out.println(this.getName());
        }
    }

3.在Java代码中看到的线程状态

(只能获取不能设置,状态的变更是JVM控制)

(1)理论中的状态

(2)Java代码中实际看到的状态

线程中可以get/set自己的优先级

注意:这个优先级的设置,只是给JVM一些建议,把自己提上去,但最终还是要听系统的

4.前台线程与后台线程/精灵线程(daemon)/守护线程

前台线程:一般是做一些有交互工作的

后台线程:一般是做一些支持工作的线程

例如:一个音乐播放器

           1.线程响应用户点击动作(前台) 

           2.线程去网络上下载歌曲(后台)

我们创造出来的线程默认都是前台线程,除非修改

public class Main {
    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        System.out.println(t.isDaemon());   // 返回 true 代表是 后台(daemon)线程
    }
}
setDaemon()方法
修改自己是前台还是后台线程

JVM进程什么时候才退出

1.必须要求所有前台都退出:所有的前台线程都退出了,JVM进程退出了

2.和后台线程没关系,即使后台线程还在工作,也正常退出。

JDK中自带的观察线程的工具

TimeUnit.SECONDS.sleep()

TimeUnit.SECONDS.sleep(1)      意思是1s后再继续运行 。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread.currentThread().setName("我是主线程");
        while (true) {
            TimeUnit.SECONDS.sleep(1);
            System.out.println("你好");
        }
    }
}

先运行再观察

可以从

中 ,找到

 

打开选择向对应方法打开观察

Thread.join()方法

控制另外的线程

A线程:1.创建B线程,并启动B线程

              2.等待B线程完成所有工作(B线程运行结束)

              3.打印B线程已经退出了

B线程:计算一个比较耗时的任务

 有无join的区别

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Main {
    private static class B extends Thread {
        @Override
        public void run() {
            // 模拟 B 要做很久的工作
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            println("B 说:我的任务已经完成");
        }
    }

    private static void println(String msg) {
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(date) + ": " + msg);
    }

    public static void main(String[] args) throws InterruptedException {
        B b = new B();
        b.start();
        println("A 自己先去吃饭");
        // 有 join 和没有 join 的区别
        b.join();
        println("A 说:B 给我把钱送来了,结账走人");
    }
}

这是没有join的结果。

 这是有join的结果

Thread常用的几个静态方法

1.Thread.sleep()

也是让线程休眠,但以毫秒为单位

TimeUnit.SECONDS.sleep(1) ==Thread.sleep(1000)

从线程的状态的角度,调用sleep(),就是让当前线程从"运行"->"阻塞"

等待某个条件:要求时间过去之后,当条件满足时,线程从“阻塞”->“就绪”,在当线程被调度器选中时开始执行之前的指令

2.Thread.current()

Thead引用,执行一个线程对象,执行的就是在哪个线程中调用的该方法,返回哪个对象。

public class Main {
    static class MyThread extends Thread{
        @Override
        public void run() {
            printCurrentThreadAttributes();
        }
    }
    private static void printCurrentThreadAttributes(){
        Thread t=Thread.currentThread();
        System.out.println(t.getId());
        System.out.println(t.getName());
    }

    public static void main(String[] args) {
        MyThread t1=new MyThread();
        t1.start();
        MyThread t2=new MyThread();
        t2.start();
    }
}

线程内容总结

(结合操作系统)

1.如何在代码中创建,启动线程

2.线程在底层的原理(OS中的线程+执行流)

3.线程结果的随机性

4.线程的常见属性(状态是重点)

5.相关工具

栈和栈帧

在没有多线程(执行流)+没有外部输入的情况下,程序的运行就是一个状态机

栈:当前执行流的当前时刻(时间停止状态时)的状态框(现实方法的调用次序)

框:栈帧(frame)装的就是运行该方法时需要的一些临时数据(主要就是具备变量)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820326.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号