首页 > 其他分享 >多线程学习第三篇

多线程学习第三篇

时间:2023-09-02 23:00:28浏览次数:42  
标签:第三篇 Thread void System 学习 线程 new 多线程 public

3、线程状态

线程五大状态:

  • 创建状态:通过new创建线程
  • 就绪状态:通过start()启动线程进入就绪状态
  • 阻塞状态:通过CPU调配进入运行状态
  • 运行状态:在运行状态时,可以进行如sleep,wait等方法使线程进入阻塞状态
  • 死亡状态:自然执行完毕、外部干涉终止线程


具体流程为:



3.1、线程的常用方法

方法 说明
setPriority(int newPriority) 更改线程的优先级
static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,别用这个方式
boolean isAlive() 测试线程是否处于活动状态

3.2、停止线程

  • 不推荐使用JDK提供的stop(); destroy();方法【已弃用】
  • 推荐线程自己停止
  • 建议使用一个标志位进行终止变量
public class TestStop implements Runnable {
    // 测试stop
	//1.建议线程正常停止--->利用次数,不建议死循环。建议使用标志位--->设置一个标志位
	//3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
    //1. 设置标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while(flag){
            System.out.println("Thread is running...." + i++);
        }
    }

    // 2. 设置一个公开的方法停止线程,转换标志位

    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();
        // main 先执行
        for (int i = 0; i < 1000; i++) {
            System.out.println("main is running..." + i);
            if(i == 900){
                //调用stop方法停止线程
                testStop.stop();
                System.out.println("Thread stop!");
            }
        }
    }

}

总结一下:

public class TestStop implements Runnable {
    //1.线程中定义线程体使用的标识
     private boolean flag = true;
    
     @Override
    public void run() {
        //线程体中使用该标识
        int i = 0;
        while(flag){
            System.out.println("......");
        }
    }
}

//对外提供方法改变标识
    public void stop(){
        this.flag = false;
    }

3.3、线程休眠——sleep()

  • sleep(时间)指定当前线程阻塞的毫秒数
  • sleep 存在异常 InterruptedException
  • sleep 时间达到后线程进入就绪状态
  • sleep 可以模拟网络延时,倒计时等 (可以故意设置延时收优化钱,不建议这样做,不道德)
  • sleep 每一个对象都有一个锁,sleep 不会释放锁

使用案例:

package com.thread.sleep;

//模拟延时:放大问题的发生性
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSleep {
    public static void main(String[] args) throws InterruptedException {
        //  down();
        // 打印当前系统时间
        Date date = new Date(System.currentTimeMillis());
        while (true){
            try {
                Thread.sleep(1000);
                //SimpleDateFormat("HH:mm:ss")是时间格式化工厂
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
                date = new Date(System.currentTimeMillis()); // 更新当前时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //public static void down() throws InterruptedException {
        //int num = 10;
        //while (true){
            //Thread.sleep(1000);
            //System.out.println(num --);
            //if(num <= 0) break;
        //}
    //}
}

3.4、线程礼让——yield()

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让 CPU 重新调度,有可能还是调度该礼让线程

注意:礼让不一定成功!

案例:

package com.thread.yield;

public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"a").start();
        new Thread(myYield,"b").start();
    }
}



class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    }
}

结果1(礼让成功):

结果2(礼让不成功):

img


3.5、合并线程——Join()

  • join合并线程,待此线程执行完成后再执行其他线程,其他线程阻塞
  • 可以想象成插队
package com.thread.Join;

public class TestJoin implements Runnable{

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        for (int i = 0; i < 300; i++) {
            if (i == 200){
                thread.join();
            }
            System.out.println("普通线程"+i);
        }

    }


    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("vip线程来了!"+i);
        }
    }
}

3.6、观测线程状态

  • Thread.State

线程状态:线程可以处于以下状态之一:

  • NEW:尚未启动的线程处于此状态。
  • RUNNABLE:在 Java 虚拟机中执行的线程处于此状态。
  • BLOCKED:被阻塞等待监视器锁定的线程处于此状态。
  • WAITING:正在等待另一个线程执行特定动作的线程处于此状态。
  • TERMINATED:已退出的线程处于此状态。

注意点:

  1. 一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。
  2. 一个线程只能启动一次,终止之后就不能再start了

案例:

package com.thread.state;

//观测测试线程状态
public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("/////");
        });


        ///观察状态
        Thread.State state = thread.getState();
        System.out.println(state); //new

        //观察启动后
        thread.start();
        state = thread.getState();//run

        //观测死亡
        while(state != Thread.State.TERMINATED){  //只要线程不终止就一直输出状态
            Thread.sleep(100);//运行时是在阻塞状态中
            state = thread.getState();//更新线程状态
            System.out.println(state);//输出状态
        }
    }
}

3.7、线程优先级

优先级:priority

Java 提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。

  • 线程的优先级用数字表示,范围从1~10
    • Thread.MIN_PRIORITY=1
    • Thread.MAX_PRIORITY=10
    • Thread.NORM_PRIORITY=5
  • 使用以下方式改变或获取优先级
    • getPriority().setPriority(int xxx)

优先级的设定建议在 start() 调度前

案例:

package com.thread.priority;
//测试线程优先级
public class TestPriority {
    public static void main(String[] args) {
        //主线程优先级
        System.out.println(Thread.currentThread().getName() + "-->"
                + Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);
        Thread t6 = new Thread(myPriority);

        //设置优先级
        t1.start();

        t2.setPriority(1);
        t2.start();

        t3.setPriority(4);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);//最大优先级 10
        t4.start();

//        t5.setPriority(-1);
//        t5.start();
//
//        t6.setPriority(11);
//        t6.start();
    }
}


class MyPriority implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());

    }
}

优先级低只是意味着获得调度的概率低,并不是高优先级必然先调用 (性能倒置问题)


3.8、守护(daemon)线程

  • 线程分为用户线程守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如后台记录操作日志,监控内存、垃圾回收等待
package com.thread.daemon;
//测试守护线程
//上帝守护你
public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认线程是用户线程
        thread.start();


        new Thread(you).start();//你启动

    }

}


//上帝
class God implements Runnable {

    @Override
    public void run() {
        while (true) {
            System.out.println("上帝永远保佑着你!");
        }
    }
}

//你
class You implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你开心的生活每一天!");
        }

        System.out.println("=========goodbye,world!");
    }
}

标签:第三篇,Thread,void,System,学习,线程,new,多线程,public
From: https://www.cnblogs.com/wangshow/p/wangshow_2.html

相关文章

  • 设计模式学习1 设计原则
    设计原则1.开闭原则对扩展开放,修改关闭。在程序需要扩展的时候,不能去修改原有代码,实现一个热插拔的效果。为了使程序的扩展性好,易于维护和升级为了达到这样的效果,我们需要使用接口和抽象类2.里氏代换原则任何基类可以出现的地方,子类一定可以出现。也就是子类继承父类时,除了添......
  • 多线程第一篇(认识多线程)
    多线程任务,进程,线程,多线程Process:进程Thread:线程1、基本概念进程在操作系统中运行的程序就是进程。程序是指令和数据的有序集合,其本身没有任何运行的含义,是静态的。进程就是执行程序的一次执行过程,它是一个动态的概念式系统资源分配的单位通常再一个进程中可......
  • 魔鬼冲刺学习笔记
    \[\huge{\textbf{魔鬼冲刺}\quad\textbf{2023.8.31-?}}\]高二是大部分OIer的最后一段竞赛时光,这真是“\(One\Last\Olympiad\)”了。所以我们开始魔鬼冲刺了!这里就用来记录这段时期的一些收获,还有学到的知识。由于停课后学习笔记给人的感觉略显凌乱,故在本文中笔者简......
  • 每周总结-第八周 多线程
    多线程概述:充分利用计算机资源,同时执行不同的操作1.计算机操作系统进程和线程2.使用java来完成多线程的编码3.线程中的常用方法4.线程同步(重点)5.死锁6.生产者消费者模型异步操作系统简介操作系统:本质上就是一个运行在一堆硬件上的巨型软件没有操作系统的话,程序想要操控......
  • 《C和指针》学习笔记
    C和指针学习笔记前置条件1.1配置环境下载vscode安装编译器:这里以MinGw-w64为例。下载MinGw-w64的安装包并解压。添加到系统环境编辑tasks.json(该文件负责项目的编译,如果需要同时编译多个文件,需要对该文件进行如下注释内的修改):{"tasks":[{......
  • 折半搜索 学习笔记
    关于算法折半搜索,又称meetinthemiddle算法。顾名思义,就是将整个搜索的过程分成两个部分分别进行搜索,然后再将两个部分搜索出来的答案进行合并,得到最终的答案。dfs搜索算法一般都是指数级别的,那么我们假如每次dfs时都有两种决策,那么我们执行dfs算法的时间复杂度为\(O......
  • 【学习笔记】二分图基础
    二分图与网络流基础(网络流待学)查看目录目录前置知识:二分图:二分图的定义:二分图的判定:例题:[NOIP2010提高组]关押罪犯二分图的匹配:匈牙利算法:例题:[ABC317G]Rearranging[ABC317G]Rearranging前置知识:tarjan强连通分量:有向图中几个点可以相互到达,就称这几个点是强连通......
  • 莫队学习笔记(如何处理增量)
    题目传送门:序列考虑我们已经求出了区间\([l,r]\)的答案,现在要求\([l,r+1]\)的答案。很明显增多的子序列有\((l,r+1),(l+1,r+1)...(r+1,r+1)\)。考虑求出\([l,r+1]\)中的最小值的位置\(p\)(可以用\(rmq~O(1)\)求出),那么\(a_p\)的贡献就是\(a_p\times(p-l+1)\),现在我......
  • 多线程|饿汉模式和懒汉模式
    单例模式是只有单个实例的模式,应用在只能有一个实例的场景中。单例模式有很多种,这里介绍饿汉模式和懒汉模式两个单例。一、饿汉模式“饿汉”是一种形象的描述,“饿汉”看到吃的就非常急切,把这种急切的形象类比到Java中就是在类加载阶段就把实例创建出来了。什么是类加载?Java代码......
  • 学习JavaScript的路径
    学习JavaScript的路径可以按照以下步骤进行:了解基本概念:首先学习JavaScript的基本概念,包括变量、数据类型、运算符、数组、对象、循环和条件语句等。可以通过阅读相关的教材、在线课程或者参考W3Schools和MDN文档等来学习。学习控制DOM元素:学习如何使用JavaScript控制DOM元素,包......