【java】多线程

news2025/1/11 15:57:10

文章目录

  • 进程和线程
  • 继承Thread类的方式实现多线程
  • 设置和获取线程的名称
  • 线程优先级 线程调度
  • 控制线程
  • 线程的生命周期
  • 多线程的实现方式
  • 案例--卖票
  • 同步方法解决数据安全问题
    • 线程安全的类
  • Lock锁
  • 生产者消费者模式
    • 概述
    • 案例

进程和线程

在这里插入图片描述
在这里插入图片描述

继承Thread类的方式实现多线程

在这里插入图片描述
MyThread.java

package heima.多线程;

public class MyThread extends Thread{

    @Override
    public void run(){
        for (int i = 0;i<100;i++){
            System.out.println(i);
        }
    }
}

package heima.多线程;

public class P1 {
    public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();

//        my1.run();
//        my2.run();//1~99

        //void start():导致此现场开始执行;java虚拟机调用此线程的run方法
        my1.start();
        my2.start();//1~99
        
        //两者区别
        //run:相当于普通的调用
        //start:启动线程;然后由虚拟机调用此线程的run()方法
    }
}

设置和获取线程的名称

在这里插入图片描述
MyThread.java

package heima.多线程;

public class MyThread extends Thread{
    public MyThread(){}

    public MyThread(String name){
        super(name);
    }
    @Override
    public void run(){
        for (int i = 0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

package heima.多线程;

public class P2 {
    public static void main(String[] args) {
//        MyThread my1 = new MyThread();
//        MyThread my2 = new MyThread();

        //1.void setName(String name):将此线程的名称更改位大于参数name
//        my1.setName("高铁");
//        my2.setName("飞机");

        //2.Thread(String name):带参构造方法--需要对MyThread内部进行修改
//        MyThread my1 = new MyThread("高铁");
//        MyThread my2 = new MyThread("飞机");
//
//        my1.start();
//        my2.start();

        //3.static Thread currentThread():返回对当前正在执行的线程对象的引用
        System.out.println(Thread.currentThread().getName());
    }
}

方法1和方法2的输出:
在这里插入图片描述

方法3的输出:
在这里插入图片描述

线程优先级 线程调度


ThreadPriority.java

package heima.多线程;

public class ThreadPriority extends Thread{
    @Override
    public void run() {
        for (int i = 0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

//后面是输出

package heima.多线程;

public class P3 {
    public static void main(String[] args) {
        ThreadPriority tp1 = new ThreadPriority();
        ThreadPriority tp2 = new ThreadPriority();
        ThreadPriority tp3 = new ThreadPriority();

        tp1.setName("高铁");
        tp2.setName("飞机");
        tp3.setName("汽车");

//        tp1.start();
//        tp2.start();
//        tp3.start();

        //public final int getPriority():返回此线程的优先级
//        System.out.println(tp1.getPriority());//5
//        System.out.println(tp2.getPriority());//5
//        System.out.println(tp3.getPriority());//5
//
//        //public final void setPriority(int newPriority):更改此线程的优先级
        tp1.setPriority(10000);//IllegalArgumentException
//        System.out.println(Thread.MAX_PRIORITY);//10
//        System.out.println(Thread.MIN_PRIORITY);//1
//        System.out.println(Thread.NORM_PRIORITY);//5

        //正确设置优先级
        tp1.setPriority(5);
        tp2.setPriority(10);
        tp3.setPriority(1);

        tp1.start();
        tp2.start();
        tp3.start();

    }
}

计算设置了优先级也同样还是有随机性,需要在次数较多的时候才能看到想要的效果

控制线程

在这里插入图片描述

  • sleep
package heima.多线程.other;

public class ThreadSleep extends Thread{
    @Override
    public void run() {
        for (int i = 0;i<100;i++){
            System.out.println(getName()+":"+i);
            try {
                //sleep使三人轮流抢到cpu时间,看上去更加和谐
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

package heima.多线程;

import heima.多线程.other.ThreadSleep;

public class P4 {
    public static void main(String[] args) {
        ThreadSleep ts1 = new ThreadSleep();
        ThreadSleep ts2 = new ThreadSleep();
        ThreadSleep ts3 = new ThreadSleep();

        ts1.setName("曹操");
        ts2.setName("刘备");
        ts3.setName("孙权");

        ts1.start();
        ts2.start();
        ts3.start();
    }
}

  • join
package heima.多线程;

import heima.多线程.other.ThreadSleep;

public class P4 {
    public static void main(String[] args) {
        ThreadSleep ts1 = new ThreadSleep();
        ThreadSleep ts2 = new ThreadSleep();
        ThreadSleep ts3 = new ThreadSleep();

        ts1.setName("曹操");
        ts2.setName("刘备");
        ts3.setName("孙权");

        ts1.start();
        //void join():等待这个线程死亡
        try{
            ts1.join();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        ts2.start();
        ts3.start();
    }
}

在这里插入图片描述

  • setDaemon
package heima.多线程;

import heima.多线程.other.ThreadSleep;

public class P4 {
    public static void main(String[] args) {
        ThreadSleep ts1 = new ThreadSleep();
        ThreadSleep ts2 = new ThreadSleep();
        ThreadSleep ts3 = new ThreadSleep();

        ts1.setName("关羽");
        ts2.setName("张飞");

        //设置主线程为刘备
        Thread.currentThread().setName("刘备");

        //设置守护线程
        ts1.setDaemon(true);
        ts2.setDaemon(true);

        ts1.start();
        ts2.start();

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

线程的生命周期

在这里插入图片描述

多线程的实现方式

在这里插入图片描述

在这里插入图片描述
MyRunnable.java

package heima.多线程.other;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

package heima.多线程;

import heima.多线程.other.MyRunnable;

public class P5 {
    public static void main(String[] args) {
        //创建MyRunnable类的对象
        MyRunnable my = new MyRunnable();

        //创建Thread类的对象,吧MyRunnable对象作为构造方法的参数
        //Thread(Runnable target)
//    Thread t1 = new Thread(my);
//    Thread t2 = new Thread(my);
        //Thread(Runnable target,String name)
        Thread t1 = new Thread(my,"高铁");
        Thread t2 = new Thread(my,"飞机");

        //启动线程
        t1.start();
        t2.start();
    }


}

案例–卖票

在这里插入图片描述

package heima.多线程;

import heima.多线程.other.SellTicket;

public class P6 {
    public static void main(String[] args) {
        //创建SellTicket类的对象
        SellTicket st = new SellTicket();

        //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
        Thread t1 = new Thread(st,"窗口1");
        Thread t2 = new Thread(st,"窗口2");
        Thread t3 = new Thread(st,"窗口3");

        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

package heima.多线程.other;

public class SellTicket implements Runnable{
    //在SellTicket类中重写run()实现卖票
    private int tickets = 100;

    @Override
    public void run() {
        while (true){
            if (tickets > 0){
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

  • 卖票案例的改进

在这里插入图片描述

在这里插入图片描述
way:
在这里插入图片描述

package heima.多线程.other;

public class SellTicket implements Runnable{
    //在SellTicket类中重写run()实现卖票
    private int tickets = 100;
    private Object obj = new Object();

    @Override
    public void run() {
        //加上代码锁,使每次只能进来一个对象
        synchronized (obj){
            while (true){
                if (tickets > 0){
                    try {
                        //让卖票动作更符合现实情况
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    }
}

在这里插入图片描述

同步方法解决数据安全问题

在这里插入图片描述

详情请见 黑马P334

线程安全的类

在这里插入图片描述
在这里插入图片描述

Lock锁

在这里插入图片描述

package heima.多线程.other;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable{
    //在SellTicket类中重写run()实现卖票
    private int tickets = 100;
    private Object obj = new Object();
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true){
            try {
                lock.lock();
                if (tickets > 0){
                    try {
                        Thread.sleep(100);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            //最后使用finally,使得就算报错最后也可以关闭锁
            }finally {
                lock.unlock();
            }

        }
    }
}


生产者消费者模式

概述

在这里插入图片描述
在这里插入图片描述

案例

在这里插入图片描述

  • 步骤1:先创建好基本的框架

BoxDemo.java

package heima.生产者消费者;

public class BoxDemo {
    public static void main(String[] args) {
        //创建奶箱对象,这是共享数据区域
        Box b = new Box();

        //创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
        Producter p = new Producter(b);

        //创建消费者对象,把奶箱对象作为构造方法参数传递,以为在这个类中要调用获取牛奶的操作
        Customer c = new Customer(b);

        //创建两个线程对象,分别把生产者和消费者对象作为构造方法参数传递
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);

        //启动线程
        t1.start();
        t2.start();
    }
}

Customer.java

package heima.生产者消费者;

public class Customer implements Runnable{
    private Box b;
    public Customer(Box b){
        this.b = b;
    }
    @Override
    public void run() {
        while (true) {
            b.get();
        }
    }
}

Producter.java

package heima.生产者消费者;

public class Producter implements Runnable{
    private Box b;

    public Producter(Box b){
        this.b = b;
    }
    @Override
    public void run() {
        for (int i = 1;i<=5;i++){
            b.put(i);
        }
    }
}

Box.java

package heima.生产者消费者;

public class Box {
    //定义一个成员变量,表示第x瓶奶
    private int milk;

    //提供存储牛奶和获取牛奶的操作
    public void put(int milk){
        this.milk = milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
    }

    public void get(){
        System.out.println("用户拿到第"+this.milk+"瓶奶");
    }
}

输出一直卡死在最后的第5瓶奶上:
在这里插入图片描述

  • 步骤2
  1. 定义奶箱状态,并进行状态判断是否等待
  2. 等待需要配对对应的锁:synchronized
  3. 在等待的同步需要:唤醒其他等待的线程notifyAll

完整版

package heima.生产者消费者;

public class Box {
    //定义一个成员变量,表示第x瓶奶
    private int milk;
    //定义一个成员变量,表示奶箱的状态
    private boolean state = false;

    //提供存储牛奶和获取牛奶的操作
    public synchronized void put(int milk){
        //如果有牛奶,等待消费
        if (state){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果没有牛奶,就生产牛奶
        this.milk = milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");

        //生产完毕之后,修改牛奶的状态
        state = true;

        //唤醒其他等待的线程
        notifyAll();
    }

    public synchronized void get() {
        //如果没有牛奶,等待生产
        if (!state) {
            try {
                wait();

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

        //如果有牛奶,就消费牛奶
        System.out.println("用户拿到第" + this.milk + "瓶奶");

        //消费完毕之后,修改奶箱状态
        state = false;

        //唤醒其他等待的线程
        notifyAll();
    }
}

package heima.生产者消费者;

public class Producter implements Runnable{
    private Box b;

    public Producter(Box b){
        this.b = b;
    }
    @Override
    public void run() {
        for (int i = 1;i<=5;i++){
            b.put(i);
        }
    }
}

package heima.生产者消费者;

public class Customer implements Runnable{
    private Box b;
    public Customer(Box b){
        this.b = b;
    }
    @Override
    public void run() {
        while (true) {
            b.get();
        }
    }
}

package heima.生产者消费者;

public class BoxDemo {
    public static void main(String[] args) {
        //创建奶箱对象,这是共享数据区域
        Box b = new Box();

        //创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
        Producter p = new Producter(b);

        //创建消费者对象,把奶箱对象作为构造方法参数传递,以为在这个类中要调用获取牛奶的操作
        Customer c = new Customer(b);

        //创建两个线程对象,分别把生产者和消费者对象作为构造方法参数传递
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);

        //启动线程
        t1.start();
        t2.start();
    }
}

在这里插入图片描述

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

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

相关文章

懵了,阿里一面就被虐了,幸获内推华为技术四面,成功拿到offer

上个月&#xff0c;哥们从某小厂离职&#xff0c;转投阿里云&#xff0c;简历优秀&#xff0c;很顺利地拿到了面试通知&#xff0c;但之后的进展却让哥们怀疑人生了&#xff0c;或者说让哥们懵逼的是&#xff0c;面试阿里云居然第一面就被吊打&#xff1f;让哥们开始怀疑自己&a…

【OpenCV-Python】教程:3-12 模板匹配

OpenCV Python 模板匹配 【目标】 利用模板匹配的方法寻找目标cv2.matchTemplate(), cv2.minMaxLoc() 【理论】 模板匹配是一个寻找大图像中目标位置的方法。OpenCV提供了函数 cv2.matchTemplate() 函数&#xff0c;通过在输入图像上滑动模板&#xff0c;将目标与滑动处的图…

[附源码]计算机毕业设计JAVA校园淘宝节系统

[附源码]计算机毕业设计JAVA校园淘宝节系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis …

【c++】STL--string

前言 最开始我们学习c语言的时候&#xff0c;我们发现刷题或者写代码都是比较麻烦的&#xff0c;如果说用c语言造一辆车&#xff0c;那么我需要用c语言先把轮子造好--各个零件&#xff0c;当我们造好之后再组装。那么c则是造好了轮子&#xff0c;只需要我们组装就好了。这里的的…

岩藻多糖-聚乙二醇-过氧化氢酶,Catalase-PEG-Fucoidan,过氧化氢酶-PEG-岩藻多糖

岩藻多糖-聚乙二醇-过氧化氢酶&#xff0c;Catalase-PEG-Fucoidan&#xff0c;过氧化氢酶-PEG-岩藻多糖 中文名称&#xff1a;岩藻多糖-过氧化氢酶 英文名称&#xff1a;Fucoidan-Catalase 别称&#xff1a;过氧化氢酶修饰岩藻多糖&#xff0c;过氧化氢酶-岩藻多糖 过氧化氢…

LiteFlow v2.9.4发布!一款能让你系统支持热更新,编排,脚本编写逻辑的国产规则引擎框架

前言 上海的天气降温让人猝不及防&#xff0c;但是我们的迭代速度却井然有序。 今天我们带来了LiteFlow v2.9.4版本。 我们每次的发布的issue有很大一部分依托于我们的使用者社区&#xff0c;社区人越来越多。我看到了使用者在使用过程中遇到的问题&#xff0c;也收集了很多…

【Java实战】这样写SQL语句性能嘎嘎好

目录 一、前言 二、SQL语句 1.【强制】不要使用 count(列名) 或 count(常量) 来替代 count(*)&#xff0c;count(*) 是 SQL92 定义的标准统计行数的语法&#xff0c;跟数据库无关&#xff0c;跟 NULL 和非 NULL 无关。 2.【强制】count(distinct col) 计算该列除 NULL 之外的…

如何实现网站首页变为黑白色?

某些时候&#xff0c;网站会根据要求将页面调成黑白色&#xff0c;一开始我还以为是将连夜把图片和文字都搞成黑白色&#xff0c;但是转念一想&#xff0c;像推送产品的京东、淘宝&#xff0c;以及展示up内容的B站、CSDN等&#xff0c;刷新之后可能展示的内容均不同&#xff0c…

从上帝视角认识SpringMVC预览

前言 SpringMVC提供了很多可拓展的组件&#xff0c;例如&#xff1a;参数解析器、拦截器、异常处理器等等。但是如果想要理解/找到这些组件工作的位置/时机&#xff0c;很多时候总是容易迷失在其层层调用的源码之中。因此才想从上帝视角来剖析它。而所谓上帝视角&#xff0c;就…

[附源码]Python计算机毕业设计Django海南琼旅旅游网

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

22.12.1打卡 漫步校园 记忆化搜索

题目里很显然只走最短路, 直接用bfs从终点到起点搜一遍将每一步到终点所需要的最短的时间存在一个dis数组中, 然后你就会发现原来的地图变成了这样 上面是地图下面是dis数组, 再看看经典记忆化搜索模板题滑雪的地图 对的, 非常地相似, 接下来的操作和滑雪基本一样, 只不过起点是…

SQL创建新的输出字段

SQL创建新的输出字段1、准备数据2、对单个字段或者多个字段进行数值计算3、数值计算4、字段拼接5、字段使用别名6、 CASE WHEN逻辑转换case when 语法一case when 语法二case when 注意点查询的值可以为任何值&#xff08;例如可以&#xff1a; select *&#xff09;可以重命名…

Docker 快速安装Jenkins完美教程 (亲测采坑后详细步骤)(转)

转载至&#xff1a;https://www.cnblogs.com/fuzongle/p/12834080.html Docker 快速安装Jenkins完美教程 &#xff08;亲测采坑后详细步骤&#xff09; Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0…

组织:阿米巴-事业部-成员公司

昨天有朋友讲到阿米巴-内部交易的成本与效率、讲到乌合之众山头团伙合并财报。昨天也都谈到方向大致正确品质大致不错极低规模成本、方向老钻错牛角尖品质精密高成本。我这篇文章就是&#xff1a;群中单句交流-朋友圈提炼段落-公众号整理成文章&#xff0c;这么来的。阿米巴&am…

从零开始带你实现一套自己的CI/CD(一)Jenkins

目录一、简介二、环境准备2.1 安装Docker和Docker-compose2.2 远程仓库Github/Gitee/GitLab2.3 部署Jenkins三、配置Jenkins3.1 Jenkins配置源码拉取地址3.2 Jenkins配置Maven构建代码3.2.1 准备jdk3.2.2 配置Maven3.2.3 Jenkins配置JDK&Maven并保存3.3 配置Jenkins任务构建…

【日常折腾】重新安装Windows7,做好ghost备份,迁移主目录,日常软件office,chrome,搜狗输入法,电脑管家,一键ghost进行备份。

目录前言1&#xff0c;关于Windows2&#xff0c;电脑起码分两个盘c、d盘3&#xff0c;因为主目录切换了&#xff0c;相关的其他人软件的数据都会迁移过去4&#xff0c;安装office软件3件套&#xff0c;不要全家桶5&#xff0c;安装电脑管家&#xff0c;还是选择腾讯吧6&#xf…

17条卢松松近期言论汇总

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 本文汇集了前段时间卢松松写的段子&#xff0c;有心情感悟、工作感悟、做直播带货、创业的感悟。关注互联网、草根创业者的朋友可以看看&#xff01; (1) 人最舒服的是什么时候呢?我认为&#xff…

RabbitMQ的工作模式

一.RabbitMQ的一些知识 1.消息属性 RabbitMQ是基于AMQP消息传输协议来实现的消息中间件&#xff1b;类似HTTP有header和body两部分数据&#xff0c;Message是RabbitMQ中的消息体概念。 Message由Properties和Body组成&#xff0c;前者是一些元信息&#xff0c;如消息的优先级…

【LeetCode】1769.移动所有球到每个盒子所需的最小操作数

题目描述 有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes &#xff0c;其中 boxes[i] 的值为 ‘0’ 表示第 i 个盒子是 空 的&#xff0c;而 boxes[i] 的值为 ‘1’ 表示盒子里有 一个 小球。 在一步操作中&#xff0c;你可以将 一个 小球从某个盒子移动到一个与之相邻的…

整理Ubuntu深度学习服务器初始化操作

前言 这两年总是换服务器&#xff0c;每次配置都挺麻烦的要搜一堆东西&#xff0c;干脆直接整理一下供自己以后参考。 版本说明 Ubuntu 20.04 桌面版 系统配置 配置SSH 安装ssh sudo apt update sudo apt install openssh-server检查ssh状态 sudo systemctl status ssh…