Java多线程-线程的状态和线程常用方法

简介: 笔记

线程共有五大状态


1 创建

线程对象被创建就进入到新状态(new)


2 就绪

调用线程的start()方法,线程进入就绪状态


3 运行

线程进入运行状态,开始执行线程体代码


4 阻塞

调用sleep,wait等方法时,线程进入阻塞状态,线程不再继续往下执行,阻塞事件解除后,重新进入就绪状态,等待cpu调度执行


5 死亡

线程中断或者结束,一旦进入死亡状态,就不能再次启动线程


线程方法


停止线程

注意:


1 不推荐使用jdk提供的stop(),destroy()方法(已废弃)

6.png

2 推荐线程自己停下来

3 建议使用一个标志位进行终止变量,当flag=false时,则终止线程运行

package com.wyh.thread;
/**
 * @program: Thread
 * @description: 利用flag让线程停止
 * @author: 魏一鹤
 * @createDate: 2022-01-01 22:38
 **/
//测试线程停止
// 注意点
// 1、建议线程正常停止---> 利用次数 不建议死循环(就算是死循环也要定义延时,不要跑的太快卡死cpu)
// 2. 建议使用标志位 --->  设置一个标志位
// 3. 不要使用stop或者destroy等过时或者jdk不建议使用的方法
public class TestThreadStop  implements  Runnable{
    //1.定义一个标识符决定线程是否运行 true为运行 false为停止
    private boolean flag=true;
    @Override
    public void run() {
        int i=0;
        // true为运行 false为停止
        while (flag){
            System.out.println("run....Thread"+i++);
        }
    }
    //2.定义一个方法转换标识符停止线程
    public void stopThread() {
        //false让线程停止
        this.flag=false;
    }
    public static void main(String[] args){
        //创建线程对象
        TestThreadStop testThreadStop = new TestThreadStop();
        //开启线程
        new Thread(testThreadStop).start();
        for (int i = 0; i < 1000; i++) {
            //主线程跑的次数
            System.out.println("main:"+i);
            if(i==900){
                //线程运行900次让线程停止   调用stop方法切换标志位,让线程停止
                testThreadStop.stopThread();
                System.out.println("线程该停止了");
            }
        }
    }
}

7.png

线程休眠 sleep

sleep(时间)指定当前线程阻塞的毫秒数(1000hs(毫秒)=1s(秒),一般一秒就够用)

sleep存在异常interruptedException

sleep时间达到后线程进入就绪状态

sleep可以模拟网络延时,倒计时等

每一个对象都有一个锁,sleep不会释放锁(线程同步)

线程休眠的作用(模拟网络延时): 放大问题的发生性

我们还是拿买票的例子演示

package com.wyh.thread;
/**
 * @program: Thread
 * @description: 线程休眠(阻塞) 模拟网络延时
 * @author: 魏一鹤
 * @createDate: 2022-01-02 20:13
 **/
//模拟网络延时
//作用    1 放大问题的发生性
public class TestThreadSleep implements Runnable {
    //票数
    int ticketNums=10;
    @Override
    public void run() {
        //火车票抢票
        while (true) {
            //如果没票了就停止
            if(ticketNums<=0){
                break;
            }
            //模拟延迟
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //Thread.currentThread().getName() 获取当前线程名称 我们是可以给线程命名的
            System.out.println(Thread.currentThread().getName() + "-->抢到了"+ticketNums--+"张票");
        }
    }
    public static void main(String[] args){
        //创建runnable接口的实现类对象
        TestThreadSleep testThreadSleep = new TestThreadSleep();
        //3个线程一起去抢票
        new Thread(testThreadSleep,"魏一鹤").start();
        new Thread(testThreadSleep,"魏一鸣").start();
        new Thread(testThreadSleep,"黄牛党").start();
    }
}

模拟倒计时

package com.wyh.thread;
/**
 * @program: Thread
 * @description: 模拟倒计时
 * @author: 魏一鹤
 * @createDate: 2022-01-02 20:22
 **/
public class TestThreadSleep2 {
    //倒计数方法
    public static void TimeDown() throws InterruptedException {
        //初始化秒数
        int timeNum=10;
        while (true){
            //线程休眠1s  1000ms=1s
            Thread.sleep(1000);
            //自减
            System.out.println(timeNum--);
            //倒到0时候停止
            if(timeNum==0){
                System.out.println("倒计时结束!");
                break;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        TimeDown();
    }
}

每1s获取当前系统时间

package com.wyh.thread;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;
/**
 * @program: Thread
 * @description: 打印当前时间
 * @author: 魏一鹤
 * @createDate: 2022-01-02 20:32
 **/
public class TestThreadSleep3 {
    //打印当前系统时间
    public static void main(String[] args) throws InterruptedException {
        //获取当前系统时间
       Date date = new Date(System.currentTimeMillis());
      while (true) {
          Thread.sleep(1000);
          System.out.println("当前时间:"+new SimpleDateFormat("HH:mm:ss").format(date));
          //更新当前时间
          date=new Date(System.currentTimeMillis());
      }
    }
}

总结sleep的特点和作用


模拟网络延迟

倒计时

sleep不会释放锁(线程同步)

sleep存在异常interruptedException

sleep时间达到后线程进入就绪状态

sleep(时间)指定当前线程阻塞的毫秒数(1000hs(毫秒)=1s(秒),一般一秒就够用


线程礼让(yield)

礼让线程,让当前允许的线程暂停,但不阻塞

让线程从运行的状态转换为就绪状态

让cpu重新调度,礼让不一定会成功,看cpu心情!

package com.wyh.thread;
/**
 * @program: Thread
 * @description: 线程礼让
 * @author: 魏一鹤
 * @createDate: 2022-01-02 20:59
 **/
//测试线程礼让 礼让不一定成功 只是让线程回到同一起跑线
public class TesThreadYield {
    public static void main(String[] args){
        //创建线程执行体
        ThreadYield threadYield=new ThreadYield();
        new Thread(threadYield,"线程A").start();
        new Thread(threadYield,"线程B").start();
    }
}
class ThreadYield implements  Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始执行");
        //线程礼让
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"结束执行");
    }
}

线程强制执行(join)

  1. join合并线程,待此线程执行完成后,再开始执行其他线程,在此期间其他线程只能阻塞等待
  2. 可以把他想象成插队
  3. 需要被捕获异常InterruptedException
package com.wyh.thread;
/**
 * @program: Thread
 * @description: 线程join强制插队
 * @author: 魏一鹤
 * @createDate: 2022-01-03 21:27
 **/
//线程join测试  可以把它想象成插队
public class TestThreadJoin implements  Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("vip来了"+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //启动线程
        TestThreadJoin testThreadJoin = new TestThreadJoin();
        Thread thread = new Thread(testThreadJoin);
        thread.start();
        for (int i = 0; i < 500; i++) {
            //如果i==500 让run线程插队执行,main方法阻塞等待,等run方法执行完之后再执行
            if(i==200){
                thread.join();
            }
            System.out.println("main启动线程"+i);
        }
    }
}


相关文章
|
2月前
|
Java
Java语言实现字母大小写转换的方法
Java提供了多种灵活的方法来处理字符串中的字母大小写转换。根据具体需求,可以选择适合的方法来实现。在大多数情况下,使用 String类或 Character类的方法已经足够。但是,在需要更复杂的逻辑或处理非常规字符集时,可以通过字符流或手动遍历字符串来实现更精细的控制。
282 18
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
200 1
|
2月前
|
Java 编译器 Go
【Java】(5)方法的概念、方法的调用、方法重载、构造方法的创建
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点使程序变得更简短而清晰。有利于程序维护。可以提高程序开发的效率。提高了代码的重用性。方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。这种就属于驼峰写法下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。
226 4
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
226 1
|
2月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
324 5
|
3月前
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
171 11
|
3月前
|
Java 开发者
Java 函数式编程全解析:静态方法引用、实例方法引用、特定类型方法引用与构造器引用实战教程
本文介绍Java 8函数式编程中的四种方法引用:静态、实例、特定类型及构造器引用,通过简洁示例演示其用法,帮助开发者提升代码可读性与简洁性。
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
178 0
|
3月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
291 16