我是靠谱客的博主 孤独蓝天,最近开发中收集的这篇文章主要介绍Thread 类的基本用法一.线程的创建二.线程中断三.线程等待四.线程的状态五.获取线程的实例总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Thread类的基本用法

  • 一.线程的创建
    • 1.定义类来继承Thread,重写run()方法
    • 2.实现 Runnable接口, 重写 run()
    • 3.继承 Thread, 重写 run,使用匿名内部类
    • 4.实现 Runnable接口, 重写 run, 使用匿名内部类
    • 5.使用lambda表达式
  • 二.线程中断
  • 三.线程等待
  • 四.线程的状态
  • 五.获取线程的实例
  • 总结

一.线程的创建

Thread 是 JAVA 标准库中描述一个线程的类,
我们常用的创建线程的方法有下面几种~

1.定义类来继承Thread,重写run()方法

run方法就表示线程要执行的具体任务(代码)

class MyThread extends Thread{
    //重写run()方法
    @Override
    public void run() {
        while(true) {
            System.out.println("hello");
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        Thread t =  new MyThread();
        //start()方法就会在操作系统中真的创建出一个线程来,并运行run方法中的具体任务
        t.start();
        //直接调用run()也可以实现代码的运行,但是这种调用方式并没有创建线程
        //t.run();
    }

2.实现 Runnable接口, 重写 run()

class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("hello");
    }
}

public class ThreaDemo3 {
    public static void main(String[] args) {
        //本质上和继承Thread重写run效果一样
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

3.继承 Thread, 重写 run,使用匿名内部类

public class ThreadDemo4 {
    public static void main(String[] args) {
        //匿名内部类
        //相当于创建了匿名的类,这个类继承了Thread
        Thread t = new Thread()
        {
            @Override
            public void run() {
                while(true)
                {
                    System.out.println("hello");
                    try {
                    //这里是让循环每1000ms跑一次,使用Thread.sleep()需要抛出异常,否则会报错
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t.start();
    }
}

4.实现 Runnable接口, 重写 run, 使用匿名内部类

 public static void main1(String[] args) {
        //实现Runnable 使用匿名内部类
        Thread t =  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("heall");
            }
        });
        t.start();
    }

5.使用lambda表达式

使用lambda也可以达到同样的效果~~

public static void main(String[] args) {
        Thread t = new Thread(() ->{
            System.out.println("hello");
        });
    }

以上的这些创建线程的方式,本质都是一样的,都是借助Thread类,在内核上创建新的PCB,加入到内核的双向链表中…
只不过区别是要执行任务的方式不一样~~

如果想要清楚地看到线程的产生,可以在JDK内置的jconsole工具中查看到线程的信息~~~~

二.线程中断

在实际开发中,我们大多是情况都不会希望线程的run是一个死循环,更希望我们能够控制这个线程,按照需求来随时结束线程(线程中断)

具体方法:
1.使用boolean变量作为循环结束标志
2.使用标准库里的内置的标志:
●获取线程内置的标志位:isInterrupted()方法
●修改线程内置的标志位:Thread.interrupt()

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                //默认标志位为false
                //Thread.currentThread()能够获取当前线程的引用
                while(!Thread.currentThread().isInterrupted())
                {
                    System.out.println("线程运行中....");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        //加个break来保证循环结束
                        break;
                    }
                }
            }
        };
        t.start();
        //在主线程中,通过t.interrupt()来设置标记位
        Thread.sleep(1000);
        //interrupt方法可能有两种行为:
        //1.如果当前线程正在运行,此时就会修改标记位为true
        //2.如果当前线程正在sleep/wait/等待锁...此时就会触发InterruptedException来进行唤醒
        t.interrupt();
    }

上述代码中的isInterrupted()是Thread的实例方法,
interrupted()这个方法也可以实现这样的目的,它是Thread类的一个静态(static)方法.(调用方法跟上面类似 , 这里就不代码演示了)~~
二者的区别:
使用静态的方法会自动清除标记位,按照上述流程调用interrupt()后标志位改为true , 但是之后会把标记位再次恢复为false;
而非静态的这个方法则 在之后不会对标记位再次进行修改~(可以根据实际的情况来判断需要使用这两个方法中的哪一种)

三.线程等待

线程与线程之间 , 调度顺序是完全不同的(这取决于操作系统调制器自身的实现),
那我们如果希望这个顺序是可控的 , 线程等待就是一种办法,来控制线程结束的先后顺序~~~
一种常见的逻辑 : t1线程,创建t2,t3,让这些新的线程来分别执行一些任务,最后让t1进行汇总任务,我们就需要t1线程最后结束,
t1.join();
这个代码就可以实现这个目的,调用这个线程时候就会阻塞等待(操作系统短时间内是不会让这个线程调度到CPU上的~) ~
我们来举个"栗子":

public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                int count  = 0;
                while(count < 5)
                {
                    count++;
                    System.out.println("线程运行中");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("运行结束");
            }
        };
        t1.start();
        System.out.println("join开始执行");
        t1.join();//阻塞等待
        System.out.println("join结束");
  }

//运行后的结果
            join开始执行
            线程运行中
            线程运行中
            线程运行中
            线程运行中
            线程运行中
            运行结束
            join结束

根据上述代码以及运行后的结果 , 可以看到 , 执行start方法,就会立刻创建一个新的线程,同时main这个线程往下执行,执行到join方法,只要t1在运行中,join方法就会一直阻塞等待,一直到t1线程执行结束(run执行完了),才会继续往下执行~~

● join()方法还有两个版本
一个是无参数的版本,相当于是"死等",什么时候对应的线程运行完了,才会继续往下执行,不然就一直等待~
另一个是有参数的版本,其中的参数就是最大等待时间~~

四.线程的状态

用于辅助系统对于线程进行调度这样的属性~
通过getState()就可以查询到当前线程对应的状态:

NEW : Thread 对象创建出来了,但内核的PCB还没创建出来.

RUNNABLE : 当前PCB也创建出来了,同时这个PCB随时待命.(就绪) 这个线程可能是正在CPU上运行,也可能实在就绪队列中排队…

TIMED_WAITING : 表示当前的pcb在阻塞队列中等待呢~(这个等待是一个"带有结束时间"的等待 : Thread.sleep())

TERMINATED: 表示当前PCB已经结束了.Thread对象还在.此时调用获取状态,得到的就是这个状态

WAITING : 线程中如果调用了wait方法,也会阻塞等待,(死等),除非其他线程唤醒了该线程.

BLOCKED : 线程中尝试进行加锁,结果发现锁已经被其他线程占用了,也会阻塞等待,等其他线程放锁后,被唤醒~~

● 当前以上的几个状态都是java的Thread类状态,和操作系统内部PCB里面的状态的值并不是完全一样的~~

五.获取线程的实例

这里我在上文第二章的 线程中断 中代码有提到过,
通过Thread.currentThread()来获取当前线程的实例,也可以通过this来获取~~

ublic static void main(String[] args) {
        Thread t  = new Thread(){
            @Override
            public void run() {
                 // 得到的就是t这个引用 ,相当于run中直接使用this
                System.out.println(Thread.currentThread().getId());
                //这是通过this的方法
                System.out.println(this.getId());
            }
        };
        t.start();
    }

上述代码中,两种方法都可以达到这样的目的,但是 this 这种方法只有在继承Thread重写run的方式来创建线程才可以,像实现Runnable接口,lambda这些方式就不可以~~

总结

以上就是我对Thread 类的一些基本用法的描述了,包含了
线程创建
线程中断
线程等待
线程状态
获取线程实例
这几个基本用法,
希望大家多提意见,我也会及时改正,~~在这里插入图片描述

最后

以上就是孤独蓝天为你收集整理的Thread 类的基本用法一.线程的创建二.线程中断三.线程等待四.线程的状态五.获取线程的实例总结的全部内容,希望文章能够帮你解决Thread 类的基本用法一.线程的创建二.线程中断三.线程等待四.线程的状态五.获取线程的实例总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部