Java多线程详解_java支持多线程

Java多线程详解_java支持多线程一、线程生命周期一个线程被实例化完成,到线程销毁的中间过程1.新生态:New一个线程对象被实例化完成,但是没有做任何操作2.就绪态度:Ready一个线程被开启,并且开始抢占CPU时间3.运

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、线程生命周期

一个线程被实例化完成,到线程销毁的中间过程

1.新生态:New

一个线程对象被实例化完成,但是没有做任何操作

2.就绪态度:Ready

一个线程被开启,并且开始抢占CPU时间

3.运行态:Run

一个进程抢到的CPU时间片,并且开始执行线程中的逻辑

4.阻塞态:Interrupt

一个线程运行中,放弃了已经获取的CPU时间片,不再参与CPU时间片的抢占,此时线程处于挂起状态

5.死亡态:Dead

一个线程对象需要被销毁

Java多线程详解_java支持多线程

二、简单创建线程的两种方式

1.继承Thread类来创建

步骤如下:

  • 定义Thread类的子类,并重写该类的run()方法
  • 创建Thread子类的实例、
  • 调用线程的start()方法启动线程
/**
 * 1.继承Thread类,自定义线程类
 */
class MyThread extends Thread {
    /**
     * 重写run方法,将并发任务写入
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("我是线程中run的方法,执行次数" + (i + 1));
        }
    }

    /**
     * 线程的命名
     */
    public MyThread(String name) {
        //在可以在实例化线程时向Thread类的构造方法传参
        super(name);
        
        //也可以调用set方法
        this.setName(name);
    }
}

2.实现Runnable接口创建

步骤如下:

  • 定义Runnable接口的实现类,重写run()方法
  • 创建Runnable实现类的实例,并在实例化Thread类时传入
  • 调用线程对象的start()方法来启动线程
/**
 * 2.通过runablele接口
 * @return
 */
Thread getRunable() {
    Runnable runnable = () -> {
        for (int i = 0; i < 10; i++) {
            System.out.println("我是线程中Runable的方法,执行次数" + (i + 1));
        }
    };
    return new Thread(runnable);
}

三、Thread线程类常用方法

Thread类有以下方法:

  • String getName():返回该线程的名称。

  • void setName(String name):设置线程名称

  • int getPriority():获取线程的优先级。

  • void setPriority(int newPriority):修改线程的优先级。

  • boolean isDaemon():获取该线程是否为守护线程。

  • void setDaemon(boolean on):将该线程标记为守护线程或用户线程。

  • static void sleep(long millis):线程阻塞

  • void interrupt():中断线程。

  • static void yield():暂停当前正在执行的线程对象,并执行其他线程。

  • void join():等待该线程终止。

  • void run():线程的执行体

  • void start() :启动线程

  • 从Object类继承来的方法:void notify();void wait()

下面对常用方法做一下简略的演示:

1.sleep 阻塞

Thread.sleep(times)

使当前线程从Running状态放弃处理器进入Block状态,休眠times毫秒,再返回Runnable状态。

/**
 * 1.线程阻塞
 */
void setSleect(){
    new Thread(() -> {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(1000);
                System.out.println("我是要阻塞的线程,执行次数" + (i + 1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "sleepThread").start();
}

2.priority 优先级

setPriority(int newPriority)

按1-10为线程的时间片分配机会设置优先级,优先级越高,执行概率越高

按以下实例,最终结果是线程1比线程2更早循环完100次

/**
 * 2.设置时间优先级
 */
void setPriority() {
    Runnable runnable = () -> {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":执行第" + (i + 1) + "次");
        }
    };

    Thread thread1 = new Thread(runnable, "线程1");
    Thread thread2 = new Thread(runnable, "线程2");

    //设置优先级
    thread1.setPriority(10);
    thread2.setPriority(1);

    //启动
    thread1.start();
    thread2.start();
}

3.yield 线程礼让

Thread.yield()

让出当前线程对象分配到的cup时间片,执行其他线程。

/**
 * 设置线程礼让
 */
void setThreadYield() {
    Thread thread1 = new Thread(getRunable(10), "线程1");
    Thread thread2 = new Thread(getRunable(35), "线程2");

    //启动
    thread1.start();
    thread2.start();
}

Runnable getRunable(int yieldNum) {
    return new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                //设置在第几个数字的时候进行礼让
                if (i == yieldNum) {
                    Thread.yield();
                    System.out.println("我让位!");
                }
                System.out.println(Thread.currentThread().getName() + ":执行第" + (i + 1) + "次");

            }
        }
    };
}

3. join 等待线程

Thread.join()

让当前线程进入等待队列,带某线程执行完毕后当前线程再开始执行,可以理解为将两个线程的关系由并行变为串行,但是并不影响其他线程的并行执行

/**
 * join
 */
void getJoin() {
    Thread t1 = new Thread(() -> {
        System.out.println("t1执行了!");

        for (int i = 0; i < 10; i++) {
            System.out.println("t1:" + i);
        }
    });

    Thread t2 = new Thread(() -> {
        System.out.println("t2等待t1执行完毕....");
        try {
            t1.join();

            for (int i = 0; i < 10; i++) {
                System.out.println("t2:" + i);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("t2执行了!");
    });

    Thread t3 = new Thread(() -> {
        System.out.println("t3不等待t1执行完毕....");
        for (int i = 0; i < 10; i++) {
            System.out.println("t3:" + i);
        }
        System.out.println("t3执行了!");
    });

    t1.start();
    t3.start();
    t2.start();
}

四、创建几个线程合适?

对于CPU密集型的计算场景,理论上线程的数量=CPU核数就是最合适的。不过在工程上,线程的数量一般会设置为CPU核数+1,这样的话,当线程因为偶尔的内存页失效或其他原因导致阻塞时,这个额外的线程可以顶上,从而保证CPU的利用率

对于I/O密集型的计算场景,最佳线程数=1+(I/O耗时/CPU耗时)

针对多核CPU,我目前见过两种比较合理的公式:

  1. 最佳线程数=CPU核数×[1+(I/O耗时/CPU耗时)]
  2. 线程数=CPU核数×目标CPU利用率×(1+平均等待时间/平均工作时间)

参考:

java多线程:创建多少线程才合适?

线程数究竟设多少合适

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170823.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • fmincon函数应用实例_abb调用例行程序

    fmincon函数应用实例_abb调用例行程序前言一般我们写接口自动化的时候,遇到复杂的逻辑,都会调用API方法来满足前置条件,Pytest的特性是无法用例之间相互调动的,我们一般只调用自己封装的API方法。而httprunner支持用例之间

    2022年7月29日
  • c++实现strstr函数_C语言字符串数组

    c++实现strstr函数_C语言字符串数组自己实现C语言中的strstr函数,采用字符一个一个进行匹配,如果不等,则从下一个位置进行匹配。/*strstr实现*/char*mystrstr(constchar*dest,constchar*src){char*tdest=dest;char*tsrc=src;while(*tdest){char*flag=tdest;//设置标志位,方便回滚。while…

    2022年10月13日
  • Json使用教程

    Json使用教程使用第三方静态库的步骤:1、编译文件生成静态库。2、把相关的.h文件放入D:\VS2005安装目录\VC\include路径下。3、把相应的.lib文件放在D:\VS2005安装目录\VC\lib路径下。在使用中只需要将json.rar中的文件添加(并包含)到项目中链接:在需要使用Json的文件中添加json.h的头文件即可使用了使用教程如下:JsonCpp是一…

    2022年4月7日
  • ArtCAM+Powermill雕刻编程加工视频教程 浮雕 玉石「建议收藏」

    ArtCAM+Powermill雕刻编程加工视频教程 浮雕 玉石「建议收藏」ArtCAM+Powermill雕刻编程加工视频教程浮雕玉石四轴雕刻链接:https://pan.baidu.com/s/1gyrg7kYYBFHzTBK9ue0G1Q提取码:67kb

    2022年9月5日
  • android游戏引擎andengine学习系列三:绘制游戏虚拟摇杆

    android游戏引擎andengine学习系列三:绘制游戏虚拟摇杆如何高效的学习,这才是我们最值得去学习的。  andengine中绘制虚拟游戏摇杆非常简单,只需要实现AnalogOnScreenControl模拟摇杆类,在设置一些属性即可。先看效果图:左边的摇杆是控制精灵上下左右移动,右边的摇杆空值精灵的旋转。代码结构跟andengine学习系列二一样,其中很多注释在系列二中有说明,在该章内便不多复述。onLoadEngine()方法:

    2022年9月16日
  • java利用异或运算的性质,对几个字符_java位运算符详解

    java利用异或运算的性质,对几个字符_java位运算符详解原标题:干货:Java异或运算符的使用方法做Java这么久,还真的从来没有用到过某些基础的Java知识。今天就遇到了一个:Java的异或运算^,这个小不点“^”就是Java的异或运算符,是不是有点小,再来个大点的看得清楚:真^假=真  假^真=真  假^假=假  真^真=假这四个是在网上copy的例子,但它却是说明了Java异或运算的基本法则,那就是:只要两个条件同时为真或假,其结果都为假(这里要…

    2022年10月4日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号