多线程基础

news2025/3/11 0:39:11

1.多线程基础概念

多线程:让程序同时做多件事情

多线程作用:提高效率

并发:在同一时间,有多个指令在单个cpu上交替执行

并行:在同一时刻,有多个指令在多个cpu上同时执行

2.多线程的实现

(1)继承Thread类来实现多线程

//第一步:写一个类mythread继承Thread类
//第二步:重写run方法,run方法里面就是线程要执行的代码
//第三步:在测试类中创建mythread类的对象th,并用th.start();来启动线程

注意是调用start方法而不是run方法

Thread中的方法:

setName方法是设置线程名字

getName方法是获取线程名字

注意看

System.out.println(getName()+"helloworld");

这个语句直接使用了getName,是因为mythread1类是Thread的子类,子类可以直接调用父类的方法

package multithreading;
//第一步:写一个类mythread继承Thread类
//第二步:重写run方法,run方法里面就是线程要执行的代码
//第三步:在测试类中创建mythread类的对象th,并用th.start();来启动线程
public class mythread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"helloworld");
        }
    }
}

package multithreading;

public class threaddemo {
    public static void main(String[] args) {
   var a = new mythread1();
   //为该线程起名
   a.setName("线程1");
   var b = new mythread1();
   b.setName("线程2");
   a.start();
   b.start();
    }
}

 运行结果可以看到线程1和线程2交替执行


(2)定义一个类去实现Runnable接口来实现多线程

//第一步:定义一个类去实现Runnable接口
//第二步:重写里面的Run方法
//第三步:在测试类里创建实现类的对象(也被称作任务对象)
//第四步:创建thread类的对象,形参就是你希望执行的线程的对象,即任务对象,再调用start()方法
package multithreading;
//第一步:定义一个类去实现Runnable接口
//第二步:重写里面的Run方法
//第三步:创建实现类的对象(也被称作任务对象)
//第四步:创建thread类的对象,形参就是你希望执行的线程的对象,即任务对象,再调用start()方法
public class MyRun implements Runnable{


    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            System.out.println(Thread.currentThread().getName()+"HelloWorld");
        }
    }
}
package multithreading;

public class threaddemo1 {
    public static void main(String[] args) {
        MyRun m = new MyRun();

        Thread t1 = new Thread(m);
        t1.setName("线程1");
        Thread t2 = new Thread(m);
        t2.setName("线程2");
        t1.start();
        t2.start();


    }
}

 System.out.println(Thread.currentThread().getName()+"HelloWorld");

这个语句中的Thread.currentThread()是获取当前线程的对象


(3)利用Callable接口和FutureTask接口来实现多线程

//第三种方式可以获取多线程运行的结果

//第一步:创建一个类MyCallable去实现Callable接口
//第二步:重写call(这个方法是有返回值的,返回多线程运行得到的结果)
//第三步:在测试类中,创建MyCallable类的对象(任务对象,表示多线程要执行的任务)
//第四步:创建FutureTask的对象(用来管理多线程运行的结果)
//第五步:创建Thread类的对象,并启动(表示线程)
package multithreading;
//第三种方式可以获取多线程运行的结果

//第一步:创建一个类MyCallable去实现Callable接口
//第二步:重写call(这个方法是有返回值的,返回多线程运行得到的结果)
//第三步:在测试类中,创建MyCallable类的对象(任务对象,表示多线程要执行的任务)
//第四步:创建FutureTask的对象(用来管理多线程运行的结果)
//第五步:创建Thread类的对象,并启动(表示线程)

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Integer> {//泛型和线程运行结果要一致
    @Override
    public Integer call() throws Exception {
        int sum=0;
        for (int i = 1; i <= 100; i++) {
            sum+=i;
        }
        return sum;
    }
}
package multithreading;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class threaddemo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //mc是线程对象,ft是用来管理传入的线程的结果的,t是用来启动线程的
        var mc  = new MyCallable();
        var ft = new FutureTask<Integer>(mc);
        var t =new  Thread(ft);

        t.start();
        System.out.println(ft.get());
    }
}

 三种实现方式的优缺点

多线程中常用成员方法

 

 设置优先级和获取优先级

优先级1~10,不设置就是默认的5,优先级越高,该线程抢占成功的概率就越大

守护线程:当非守护线程运行结束时,守护线程也就没有执行的必要了,会慢慢结束

礼让线程:让线程尽可能抢占均匀

插入线程:t.join();    把t线程插入到当前线程之前,当插入的线程结束后再执行之前那个线程

线程的生命周期



线程安全问题--同步代码块

当多个线程同时运行时,出现的不合理情况

if (ticket <= 0) {
    // 卖完了
    break;
} else {
    ticket--;
    System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticket + "张");
}

窗口三在卖票,还剩下98张
窗口一在卖票,还剩下98张
窗口一在卖票,还剩下96张
窗口三在卖票,还剩下95张
窗口二在卖票,还剩下95张
 

 这是出现了多个窗口同时卖同一张票的情况,因为多个线程同时运行到了某条语句

窗口一在卖票,还剩下0张
窗口三在卖票,还剩下-1张
 

这是出现负数票,因为运行过程中出现了脏数据 ,线程三运行到 判断票数时,票数还大于0,可当运行到   ticket--;时,其他线程在这之前已经   ticket--了,导致了出现负数

同步代码块

语法:

synchronized(任意对象) {
    多条语句操作共享数据的代码
}
 

当有多个线程时,这个(任意对象)必须是静态唯一的,就是说是唯一的锁,不然每个线程用各自的锁不就相当于没锁了吗

只要有一个线程进入该代码块,该块就被锁住,其他线程无法进入,当线程执行完毕出来,就自动解锁,

同步方法

同步方法不需要指定锁对象,而且同步方法可以锁住方法中所有代码,故同时只能有一个线程运行同步方法中的代码。

修饰符 synchronized 返回值类型 方法名(方法参数) {

}

Lock锁

唤醒机制,生产者和消费者

Cook类

package lock;

public class Cook extends   Thread{//表示Cook能创建线程对象

    @Override
    public void run() {
        //1.写循环
        //2.写同步代码块
        //3.判断共享数据是否到达末尾(到达末尾)
        //4.判断共享数据是否到达末尾(没有到达末尾,就执行

        while(true)
            synchronized (Desk.lock){
            if(Desk.count==0){//总次数为0表示吃货已经吃饱
                break;
            }
            else{//还有次数
                if(Desk.foodFlag==1) {//如果桌子上有面条,厨师等吃货吃完这碗就好了
                    try {
                        Desk.lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                else{
                    //桌子上没有面条,厨师就做面条
                    System.out.println("厨师开始做面条");

                    //做完就要修改桌子数据,0改成1
                    Desk.foodFlag =1;
                    //唤醒吃货来吃
                    Desk.lock.notifyAll();

                }



            }



            }
    }
}

Foodie类

package lock;

public class Foodie extends Thread{

    @Override
    public void run() {
        //1.写循环
        //2.写同步代码块
        //3.判断共享数据是否到达末尾(到达末尾)
        //4.判断共享数据是否到达末尾(没有到达末尾,就执行核心逻辑)


        while(true)
            synchronized (Desk.lock)
            {
            if(Desk.count==0)
                break;
            else{
                //先判断桌子上是否有面条
                //没有就等
                //有就吃
                //吃完之后唤醒厨师线程
                //总次数减1
                //修改桌子状态,就是本来桌子上有面条,是1,吃完就没了,就要修改桌子状态为0

                if(Desk.foodFlag==0)
                {//桌子上没有面条
                    //没有就等待
                    try {
                        Desk.lock.wait();//等待的方法要用锁对象去调用
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }


                }
                else{//表示桌子上有面条
                    //有就开吃
                    //能吃的面条湾数减一
                    Desk.count--;
                    System.out.println("吃货在吃面条,还能再吃"+Desk.count +"碗");
                    //吃完就唤醒厨师
                    Desk.lock.notifyAll() ;//表示唤醒绑定该锁对象的所以线程
                    //修改桌子状态
                    Desk.foodFlag  =0;


                }
                }
            }

    }
}

Desk类

package lock;

public class Desk {

    //该类控制生产者和消费者的执行

    //0:没食物,1:有食物
    public static  int  foodFlag =0;


    //总个数
    public  static  int count =10;

    //锁对象
    //只是名字是锁,用来做  synchronized ()的锁对象
    public  static Object lock = new Object();

}

测试类

package lock;

public class ThreadDemo {
    public static void main(String[] args) {
        //完成生产者和消费者的代码
        //实现线程轮流交替执行的效果

        //创建线程的对象
        Cook c = new Cook();
        Foodie f = new Foodie();


        //给线程设置名字
        c.setName("厨师");
        f.setName("吃货");

        //开启线程
        c.start();
        f.start();




    }

}

运行结果

唤醒机制:阻塞队列

线程状态

线程池

 自定义线程池

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/433448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络问题

1.网络分层结构及其必要性 五层体系结构&#xff1a; 七层结构&#xff1a; 应用层&#xff1a;网络服务与最终用户的一个接口&#xff0c;常见的协议有&#xff1a;HTTP FTP SMTP SNMP DNS.表示层&#xff1a;数据的表示、安全、压缩。&#xff0c;确保一个系统的应用层所发…

『Linux笔记』Linux设置SSH远程连接Docker容器

Linux设置SSH远程连接Docker容器 文章目录 一. 创建容器二. 进入容器/设置密码三. 安装ssh及修改配置四. 重启ssh服务五. 远程连接六. 提交运行中的容器docker commit参考文章 一. 创建容器 在ubuntu镜像中创建容器&#xff0c;并将docker服务器的60222端口映射到容器的22端口…

如何将Tomcat集成到IDEA中并启动项目?

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 服务器软件&#xff1a;apache-tomcat-8.5.27 目录一、为什么要将Tomcat集成到IDEA里&#xff1f;二、集成步骤2.1 在IDEA中创建Tomcat2.2 创建java的企业级模块&#xff08;动态的we…

同为科技(TOWE)8路RS485通讯智能机柜PDU时序电源管理器

智能PDU电源时序管理器的出现是为了更好地管理数据中心和服务器机房的电源&#xff0c;以提高其可靠性和效率。在传统的机房电力管理中&#xff0c;运维人员需要手动控制每个设备的电源开关和电力分配&#xff0c;这种方式不仅效率低下&#xff0c;而且容易出现操作失误和电源供…

记一次mysql cpu 异常升高100%问题排查

此服务器为一个从库&#xff0c;用于数据的导出业务&#xff0c;服务器配置较低&#xff0c;日常的慢sql也比较多。 上午11点左右cpu异常告警&#xff0c;如下图所示&#xff0c; cpu使用率突增到50%&#xff0c;下午2点左右突增到100% &#xff0c;登录服务器top命令查看cpu升…

基于脚手架@vue/cli 5.0.8搭建vue3项目教程

基于脚手架vue/cli 5.0.8搭建vue3项目教程 前言 前言 脚手架可以快速的帮我们搭建一个项目&#xff0c;而不需要我们从头开始去配置和引入插件&#xff0c;使用脚手架5.0.8版本创建的项目&#xff0c;局部webpack是5.x版本的&#xff0c;因此所有的配置均需要使用支持5.x版本的…

Shader Graph11-Detail Normal Map(法线贴图叠加)

本次我们希望通过叠加两个法线贴图来增加细节。 一、准备资源 我们需要一个模型&#xff0c;1张纹理贴图&#xff0c;2张法线贴图 我们可以在商店下载&#xff0c;这个mesh资源来做这个例子 打开OldWest->VOL3->Meshes&#xff0c;找到SM_Blankets_01c这个布的模型&am…

QoS技术原理

QoS技术的产生 随着网络的不断发展&#xff0c;网络规模及流量类型的不断增加&#xff0c;使得互联网流量激增&#xff0c;产生网络拥塞&#xff0c;增加转发时延&#xff0c;严重时还会产生丢包&#xff0c;导致业务质量下降甚至不可用。所以&#xff0c;要在IP网络上开展这些…

Abaqus 2022最新版下载软件安装包 永久安装包详细安装流程

Abaqus 2022是一套功能强大的工程模拟的有限元软件&#xff0c;其解决问题的范围从相对简单的线性分析到许多复杂的非线性问题。Abaqus包括一个丰富的、可模拟任意几何形状的单元库。并拥有各种类型的材料模型库&#xff0c;可以模拟典型工程材料的性能&#xff0c;其中包括金属…

浏览器网络之TCP与UDP

文章目录 网络模型TCP协议建立连接——三次握手断开连接——四次挥手为什么要三次握手与四次挥手 不常使用的协议——UDPTCP与UDP的区别UDP的使用场景 总结 网络模型 在理解TCP与UDP 之前&#xff0c;首先需要对网络结构有一些基本的认识&#xff0c;在互联网发展的初期&#…

【golang学习笔记】——(二)配置golang vscode开发环境

本次学习采用vscode进行开发&#xff0c;vscode有比较成熟的插件&#xff0c;使用起来比较方便。 一、插件下载 搜索“Go”&#xff0c;第一个插件即为go的开发插件&#xff0c;进行安装即可。 二、go辅助插件下载 使用快捷键&#xff1a;CtrlShiftP 输入Go:Install/Update T…

SpringCloud之组件Hystrix简介

服务雪崩介绍 服务提供者不可用导致服务调用者也跟着不可用&#xff0c;以此类推引起整个链路中的所有微服务都不可用&#xff0c; 服务提供者A因为某种原因出现故障&#xff0c;那么服务调用者服务B依赖于服务A的请求便无法成功调用其提供的接口&#xff0c;假以时日依赖于服务…

电子表格软件能解决什么问题?

在当下的时代&#xff0c;全球经济非常活跃&#xff0c;对于企业来说&#xff0c;经营的成果需要“用数字说话”——以数字来反映经营管理的的状况&#xff0c;这些都离不开报表&#xff0c;可以说报表的需求是无处不在的。 在企业所有的科技类项目中报表是最基本的功能。作为…

第二章:uniapp整合axios之真机测试两问题

第二章&#xff1a;uniapp整合axios之真机测试两问题 上一章节&#xff0c;笔者编写了uniapp整合axios并实现前后端跨域请求的方案&#xff0c;完成了这些基本配置后&#xff0c;在浏览器端的测试基本是可以完成了&#xff0c;但是当笔者将程序运行到手机时&#xff0c;却出现…

4个 Python 库来美化你的 Matplotlib 图表

Matplotlib是一个被广泛使用的Python数据可视化库&#xff0c;相信很多人都使用过。 但是有时候总会觉得&#xff0c;Matplotlib做出来的图表不是很好看、不美观。 今天我就给大家分享四个美化Matplotlib图表的Python库&#xff0c;它们可以轻松让你的Matplotlib图表变得好看…

fastjson 反序列化之mysql JDBC 利用

前言&#xff1a; 在打春秋云境Exchange 靶场时&#xff0c;入口点是华夏ERP 2.3版本系统&#xff0c;存在fastjson 反序列化漏洞&#xff0c;在尝试常见的fastjson利用链反弹shell都没有反应&#xff0c;最终使用mysql JDBC利用链反弹shell成功。在此记录一下。 复现本地靶场…

QT安装mysql驱动和使用ODBC连接mysql

文章目录 QT安装mysql驱动和使用ODBC连接mysql使用驱动连接mysql编译mysql驱动连接mysql 使用ODBC连接mysql QT安装mysql驱动和使用ODBC连接mysql 上一篇博文中提到了mysql的使用&#xff0c;但是很多人在使用新版Qt连接mysql的时候出现连接不上或者是没有mysql驱动的问题&…

不懂就问,Milvus 新上线的资源组功能到底怎么样?

在近期更新的 Milvus 2.x 版本中&#xff0c;我们上线了在社区中呼声一直很高的【资源组功能】。有了这个功能&#xff0c;用户再也不需要“为每个 collection 部署一套 Milvus 服务”的方案&#xff0c;轻松实现对 Query Node 资源进行分组管理&#xff0c;达到物理资源隔离的…

【C++】STL中的容器适配器 stack queue 和 priority_queue 的模拟实现

STL中的容器适配器 一、容器适配器1、什么是容器适配器2、STL标准库中的容器适配器 二、stack的模拟实现1、stack的简单介绍2、栈的模拟实现 三、queue的模拟实现1、queue的简单介绍2、queue的模拟实现 四、priority_queue的模拟实现1、priority_queue的简单介绍2、priority_qu…

家用洗地机哪款好用?好用的洗地机分享

要说现在家居清洁用什么单品更省心&#xff0c;洗地机必须要算一项。虽然这在国际上也不是什么新鲜的概念了&#xff0c;但是在国内兴起也只是这几年的事&#xff0c;关于家用洗地机什么牌子最好之类的问题也是很多人都比较关心的问题。我个人也是不喜欢做家务的&#xff0c;家…