木舟0基础学习Java的第二十天(线程,实现,匿名有名,休眠,守护,加入,设计,计时器,通信)

news2024/9/23 1:21:14

多线程

并发执行的技术

并发和并行

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

并行:同一时间 有多个指令 在多个CPU上 执行

进程和线程

进程:独立运行 任何进程 都可以同其他进程一起 并发执行

线程:是进程中的单个顺序控制流 是一条执行路径 线程又分为单线程和多线程

单线程:

多线程:JVM是多线程 其实就是JVM的主线程和垃圾回收线程在工作 结果在切换着运行

多线程的运行方式:他们拥有相等的运行权限 但运行过程是谁先抢到CPU的运行权限那么谁就先运行

线程的五种状态:新建,就绪,运行,堵塞,死亡

线程的实现:

方式一:继承Thread类

建立一个类继承Thread类 那么这类创建的对象可以并发的作为独立线程运行

继承的好处是可以使用父类中的方法 比较简单

继承的弊端是如果已经有父类了 就不可以再继承了 一个子类只能继承一个父类

public class Demo02 {
    public static void main(String[] args) {
        MyThread1 m1=new MyThread1();
        MyThread2 m2=new MyThread2();
        MyThread3 m3=new MyThread3();
        //普通方法
       /* m1.run();
        m2.run();
        m3.run();*/
        //start开启新线程 内部会根据cpu的分配自动执行run
        m1.start();
        m2.start();
        m3.start();//相当于跑步比赛的发令枪 启动后主线程与其他线程都会等待抢到cpu的执行权
        //谁先抢到谁运行
    }
}
//建立一个类继承Thread类 那么这类创建的对象可以并发的作为独立线程运行
class MyThread1 extends Thread{
    public void run(){
        for (int i = 0; i <10000000 ; i++) {
            System.out.println("1号线程");
        }
    }
}
class MyThread2 extends Thread{
    public void run(){
        for (int i = 0; i <10000000 ; i++) {
            System.out.println("2号线程");
        }
    }
}
class MyThread3 extends Thread{
    public void run(){
        for (int i = 0; i <10000000 ; i++) {
            System.out.println("3号线程");
        }
    }
}

方式二:实现Runnable接口

建立一个类实现Runnable接口

接口的好处是就算实现了其他接口 也可以使用

接口的弊端 操作不便利 需要先获取Thread线程对象

public class Demo03 {
    public static void main(String[] args) {
        My1 my1=new My1();
        Thread t1=new Thread(my1);
        My2 my2=new My2();
        Thread t2=new Thread(my2);
        t1.start();
        t2.start();
    }
}
//定义一个类 实现Runnable接口 重新run方法
   class My1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <10000000 ; i++) {
            System.out.println("1号线程");
        }
    }
}
   class My2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <10000000 ; i++) {
            System.out.println("2号线程");
        }
    }
}

start()方法把当前线程交给了底层的  ThreadGroup group[]数组管理

Jvm根据随机分配的cpu执行权调用run()  随机分配的cpu执行权是相等概率的

匿名内部类实现线程

方式一:继承Thread类

 public static void main(String[] args) {
        new Thread(){
            public void run(){
                for(int i=0;i<10000000;i++){
                    new Student();
                    System.out.println("线程1");
            }
        }
    }.start();
        new Thread(){
            public void run(){
                for(int i=0;i<10000000;i++){
                    new Student();
                    System.out.println("线程2");
                }
            }
        }.start();

}

方式二:实现Runnable接口

  public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    System.out.println("1号线程");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    System.out.println("2号线程");
                }
            }
        }).start();
    }

有名内部类实现线程

 public static void main(String[] args) {
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    System.out.println("1号线程");
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    System.out.println("2号线程");
                }
            }
        });
        t1.start();
        t2.start();
    }

设置名字和获取名字(getName() setName())

可以在运行中获取当前线程的对象Thread.currentThread()

public class Demo06 {
    public static void main(String[] args) {
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    //Thread.currentThread()获取当前运行的线程对象
                    //获取名字getName()
                    System.out.println(Thread.currentThread().getName());
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <10000000 ; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        });
        //设置名字
        t1.setName("线程1");
        t1.start();
        t2.setName("线程2");
        t2.start();
    }
}
通过构造方法给线程取名
public class Demo06 {
    public static void main(String[] args){
        //通过构造方法给线程取名
        Thread t1=new Thread(new M1(),"my1");
        Thread t2=new Thread(new M2(),"my2");
        t1.start();
        t2.start();
    }
}
class M1 implements Runnable{

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

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

休眠

Thread.sleep(100);让当前线程休眠100毫秒

class MM1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <100000 ; i++) {
            System.out.println(Thread.currentThread().getName());
            try {
                //让当前线程休眠100毫秒
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

守护线程

线程.setDaemon(true);

设置一个线程为守护线程 该线程不会单独执行 当其他非守护线程都执行结束后 再自动退出

public class Demo08 {
    public static void main(String[] args) {
        M2Thread m2=new M2Thread();
        m2.setName("线程2");
        m2.start();

        M1Thread m1=new M1Thread();
        m1.setName("线程1");
        m1.start();

        //守护线程不会单独执行
        Thread1 t=new Thread1();
        t.setName("守护线程");
        t.setDaemon(true);//设置true为守护线程 主线程结束 守护线程也结束
        t.start();
    }
}
class M1Thread extends Thread{
    public void run(){
        for (int i = 0; i <100 ; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}
class M2Thread extends Thread{
    public void run(){
        for (int i = 0; i <100 ; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}
class Thread1 extends Thread{
    public void run(){
        for (int i = 0; i <10000 ; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

加入线程

线程.join(可以限定时间 也可以不限定);

  public static void main(String[] args) {
        Thread t1=new Thread("女朋友的电话"){
            public void run(){
                for (int i = 0; i <100 ; i++) {
                    System.out.println(Thread.currentThread().getName()+i);
                }
            }
        };
        Thread t2=new Thread("老板的电话"){
            public void run(){
                for (int i = 0; i <100 ; i++) {
                    System.out.println(Thread.currentThread().getName()+i);
                    if(i==50){
                        try {
                            //加入女朋友的线程 基本全面占有cpu执行权
                            // t2线程要等待t1线程执行完毕后才可以继续执行
                            t1.join();//可以限定时间
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                }
            }
        };
        t1.start();
        t2.start();
    }

礼让(了解)

Thread.yield();//让出cpu的执行权给别的线程

设置优先级:(优先级1-10 默认为5)

线程.setPriority(10);

同步(同步锁,同步代码块)

注意:开发中尽量不要嵌套同步代码块 可能会死锁
关键字:synchronized(同步锁使用的多)
public class Test {
    String s="123";
    //同步锁 在方法中加synchronized关键字
    //public synchronized void show1(){} 
     public synchronized void show1(){
        System.out.print("我");
        System.out.print("爱");
        System.out.print("学");
        System.out.print("习");
        System.out.println("-----------");
    }
    public void show2(){
        //同步代码块synchronized(s锁对象){}
        //多个同步代码块如果使用相同的锁对象 那么他们就是同步的
     synchronized(s){ 
        System.out.print("想");
        System.out.print("睡");
        System.out.print("觉");
        System.out.println("===========");}
    }
}

线程安全

synchronized线程安全  没有synchronized线程不安全

Vector线程安全  ArrayList线程不安全

Stringbuffer安全  stringBuilder不安全

HashTable安全  HashMap不安全

设计模式

单例设计模式

public class Single {
    private Single(){//私有构造方法 不让其他类new对象
    }
   static Single s=new Single();
}
    public static void main(String[] args) {
        Single s1=Single.s;
        Single s2=Single.s;
        System.out.println(s1==s2);//true
        Single s3=null;//对象可以被修改
        Single s4=Single.s;
        System.out.println(s3==s4);//false
    }
饿汉式(直接加载)

节约时间 浪费空间(例如:安卓手机应用可以在后台运行)

一旦被加载进来 就创建好了对象 不管是否使用 都在内存中
public class Single1 {
    private Single1(){//私有构造方法 不让其他类new对象
    }
   static Single1 s=new Single1();
    //饿汉式
    public static Single1 getInstance(){
        //一旦被加载进来 就创建好了对象 不管是否使用 都在内存中
        return s;
    }
}
public static void main(String[] args) {
        Single s1=Single.getInstance();
        Single s2=Single.getInstance();
        System.out.println(s1==s2);//true
    }
懒汉式(延迟加载)

节约空间 浪费时间(例如:苹果手机应用不挂后台)

什么时候用 什么时候才创建
public class Single2 {
    private Single2(){}
    public static Single2 s=null;
    //懒汉式
    public static Single2 Instance(){
        //需要的时候才创建对象
        if(s==null){
            s=new Single2();
        }
        return s;
    }
}

Runtime类单例(查API)

每个 Java 应用程序都有一个Runtime类实例 使应用程序能够与其运行的环境相连接 可以通过 getRuntime方法获取当前运行时。

应用程序不能创建自己的 Runtime类实例

 public static void main(String[] args) {
        Runtime r=Runtime.getRuntime();
        try {
            //r.exec("mspaint");//打开画图
            //r.exec("notepad");//打开记事本
            //r.exec("shutdown -s -t 6000");//6000秒后自动关机
            //r.exec("shurdown -a");//取消自动关机
            //r.exec("百度去");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

Timer类(计时器)

用来定时执行程序的类
public class MyTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("起床了");
    }
}
 public static void main(String[] args) {
        //用来定时执行程序的类
        Timer t=new Timer();
        //5秒后执行任务
        t.schedule(new MyTask(),new Date(System.currentTimeMillis()+5000));
        //5秒后执行任务 每隔1秒重复执行
        t.schedule(new MyTask(),new Date(System.currentTimeMillis()+5000),1000);
    }

线程通信(等待,唤醒)

必须在同步代码块中 使用同步锁对象调用(唤醒 等待 唤醒 等待)代码交替运行

并发执行时 默认情况下 cpu的执行权 是随机的 谁先抢到谁先执行

如果希望有规律的执行 就可以用线程通信

notify唤醒 wait等待

案例:两个方法交替

public class TestThread2 {
    public synchronized void print(){
        System.out.print("我");
        System.out.print("爱");
        System.out.print("学");
        System.out.print("习");
        System.out.println("-----------");
        this.notify();//唤醒正在等待的线程
        try {
            this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    public synchronized void show(){
        System.out.print("想");
        System.out.print("睡");
        System.out.print("觉");
        System.out.println("===========");
        this.notify();//唤醒正在等待的线程
        try {
            this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
 public static void main(String[] args) {
        TestThread2 tt2=new TestThread2();
        new Thread(){
            public void run(){
               while(true){ tt2.print();}
            }
        }.start();
        new Thread(){
            public void run(){
                while(true){ tt2.show();}
            }
        }.start();
    }

案例:三个和三个以上方法交替

public class TestThread3 {
    boolean b1=true;
    boolean b2=false;
    boolean b3=false;
    public synchronized void show1() {
        if (b3) {
            System.out.print("我");
            System.out.print("爱");
            System.out.print("学");
            System.out.print("习");
            System.out.println("-----------");
        }
        b1 = true;
        b3 = false;
        this.notifyAll();//唤醒所有正在等待的线程
        try {
            this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    public synchronized void show2(){
        if(b1){
            System.out.print("想");
            System.out.print("睡");
            System.out.print("觉");
            System.out.println("===========");
        }
        b2=true;
        b1=false;
        this.notifyAll();//唤醒所有正在等待的线程
        try {
            this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    public synchronized void show3(){
        if(b2){
            System.out.print("想");
            System.out.print("吃");
            System.out.print("饭");
            System.out.println("~~~~~~~~~~~");
        }
        b2=false;
        b3=true;
        this.notifyAll();//唤醒所有正在等待的线程
        try {
            this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
 public static void main(String[] args) {
        TestThread3 tt3=new TestThread3();
        new Thread(){
            public void run(){
                while(true){
                    tt3.show1();
                }
            }
        }.start();
        new Thread(){
            public void run(){
                while(true){
                    tt3.show2();
                }
            }
        }.start();
        new Thread(){
            public void run(){
                while(true){
                    tt3.show3();
                }
            }
        }.start();
    }

wait和sleep区别

wait():释放锁 等待并释放锁让别的线程运行

sleep():不释放锁 在指定的时间抱着锁睡 时间一到马上醒来

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

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

相关文章

鸿蒙语言基础类库:【@system.mediaquery (媒体查询)】

媒体查询 说明&#xff1a; 从API Version 7 开始&#xff0c;该接口不再维护&#xff0c;推荐使用新接口[ohos.mediaquery]。本模块首批接口从API version 3开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import mediaquery from sy…

【进阶篇-Day10:JAVA中泛型、平衡二叉树、红黑树、TreeSet集合的介绍】

目录 1、泛型1.1 泛型类1.2 泛型方法1.3 泛型接口1.4 泛型通配符1.5 总结 2、数据结构&#xff08;树&#xff09;2.1 树的基本介绍2.2 二叉树的介绍2.2.1 概念&#xff1a;2.2.2 二叉查找树的介绍&#xff1a;2.2.3 二叉查找树添加节点&#xff1a;2.2.4 二叉查找树查找节点&a…

window11 部署llama.cpp并运行Qwen2-0.5B-Instruct-GGUF

吾名爱妃&#xff0c;性好静亦好动。好编程&#xff0c;常沉浸于代码之世界&#xff0c;思维纵横&#xff0c;力求逻辑之严密&#xff0c;算法之精妙。亦爱篮球&#xff0c;驰骋球场&#xff0c;尽享挥洒汗水之乐。且喜跑步&#xff0c;尤钟马拉松&#xff0c;长途奔袭&#xf…

从零开始读RocketMq源码(五)Consumer消费Message流程解析

目录 前言 准备 拉取服务和重平衡服务启动 初识PullRequest 重平衡服务 对重平衡资源进行排序 MessageQueue消息队列集合来源 Consumer消费者集合数据来源 确实分配资源策略 执行分配策略 初始化ProcessQueue 初始化PullRequest 内存队列填充PullRequest 消息拉取…

hackmyvm--Decode

环境 靶机&#xff1a;ip未知 攻击机kali&#xff1a;192.168.233.128 192.168.56.101 主机探测 锁定靶机ip为108 端口扫描 nmap -p- -T4 -A 192.168.56.108 常规套路80和22 web打点 dirsearch -u http://192.168.56.108/ 访问robots,txt文件 访问/decode 发现其自动添加了/,怀…

Chromium源码阅读(9):了解Log模块

Chromium许多日志被TraceEvent代替了&#xff0c;因此TraceEvent出现的频率要比Log高很多。 但是也有不少场景使用Log。 在blink&#xff0c;Log的实现由base提供&#xff0c;而blink/render/core/base/logging.h进行了二次封装。 日志系统的设计细节 错误对话框处理 错误消…

Qt第十二章 样式表

样式表 文章目录 样式表1.样式表盒子模型 2.选择器选择器类型伪状态选择器Pseudo-State 3.控件示例4继承自QWidget的类&#xff0c;设置qss样式表没有效果&#xff0c;需要重写paintEvent 1.样式表 盒子模型 2.选择器 样式表语法&#xff0c;选择器{属性1:值;属性2:值;}如果只…

韦东山嵌入式linux系列-驱动进化之路:设备树的引入及简明教程

1 设备树的引入与作用 以 LED 驱动为例&#xff0c;如果你要更换LED所用的GPIO引脚&#xff0c;需要修改驱动程序源码、重新编译驱动、重新加载驱动。 在内核中&#xff0c;使用同一个芯片的板子&#xff0c;它们所用的外设资源不一样&#xff0c;比如A板用 GPIO A&#xff0c…

鸿蒙仓颉语言【类型class】

类与结构&#xff08;class & struct&#xff09; 面向对象的编程语言&#xff0c;必不可少的基础元素&#xff0c;类或者叫类型&#xff0c;在仓颉中类可以抽象(abstract)、继承&#xff08;<:&#xff09;&#xff0c;公开&#xff08;Public&#xff09;或者私有&am…

在jsPsych中使用Vue

jspsych 介绍 jsPsych是一个非常好用的心理学实验插件&#xff0c;可以用来构建心理学实验。具体的就不多介绍了&#xff0c;大家可以去看官网&#xff1a;https://www.jspsych.org/latest/ 但是大家在使用时就会发现&#xff0c;这个插件只能使用js绘制界面&#xff0c;或者…

【算法专题】归并排序

目录 1. 排序数组 2. 交易逆序对的总数 3. 计算右侧小于当前元素的个数 4. 翻转对 总结 1. 排序数组 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 今天我们使用归并排序来对数组进行排序&#xff0c;实际上&#xff0c;归并排序和快速排序是有一定相似之处的&a…

什么是蓝牙芯片?蓝牙芯片和蓝牙模块的区别

蓝牙芯片&#xff0c;是一种集成了蓝牙无线通信技术的微型电子元件。它如同一个微小的通信枢纽&#xff0c;能够在各种电子设备之间建立无线连接&#xff0c;实现数据的传输与共享。蓝牙芯片的设计精妙而复杂&#xff0c;内部集成了射频前端、数字基带、协议栈等多个功能模块&a…

Linux中nohup(no hang up)不挂起,用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。

nohup的英文全称是 no hang up&#xff0c;即“不挂起”。这个命令在Linux或Unix系统中非常有用&#xff0c;主要用于在系统后台不挂断地运行命令&#xff0c;即使退出终端也不会影响程序的运行。默认情况下&#xff08;非重定向时&#xff09;&#xff0c;nohup会将输出写入一…

linux中常见的协议、服务端口整理汇总

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

排序系列 之 插入排序

&#xff01;&#xff01;&#xff01;排序仅针对于数组哦本次排序是按照升序来的哦 介绍 插入排序英文名为InsertSort 基本思路 1、认为数组当中的第一个数值已经排好序了2、定义一个游标从第二个数值开始不断地向后进行遍历3、游标指向的数据插入已经排好序的数组中 代码…

力扣刷题之2959.关闭分部的可行集合数目

题干描述 一个公司在全国有 n 个分部&#xff0c;它们之间有的有道路连接。一开始&#xff0c;所有分部通过这些道路两两之间互相可以到达。 公司意识到在分部之间旅行花费了太多时间&#xff0c;所以它们决定关闭一些分部&#xff08;也可能不关闭任何分部&#xff09;&…

AV1 编码标准屏幕内容编码技术概述

AV1 屏幕内容编码 为了提高屏幕捕获内容的压缩性能&#xff0c;AV1采用了几种编码工具&#xff0c;例如用于处理屏幕画面中重复模式的内帧内块复制&#xff08;IntraBC&#xff09;&#xff0c;以及用于处理颜色数量有限的屏幕块的调色板模式。 帧内块拷贝 AV1 编码中的 Intra …

【Vue】快速入门:构建你的第一个Vue 3应用

文章目录 一、Vue简介二、环境搭建1. 安装Node.js和npm2. 安装Vue CLI 三、创建Vue项目四、项目结构介绍五、组件基础创建一个组件使用组件 六、模板语法插值指令v-bindv-ifv-for 七、事件处理八、状态管理安装Vuex创建Store使用Store 九、路由基础安装Vue Router配置路由使用路…

FFmpeg播放视频

VS2017+FFmpeg6.2.r113110+SDL2.30.5 1.下载 ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC++控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下,并设置调试命令

24年Hvv准备,6大方向,33篇技战法

进去不少小伙伴后台留言说需要技战法&#xff0c;因此小编对市面上的技战法进行了收集和总结&#xff0c;并对收集来的技战法进行了分类&#xff0c;总共分了6大类&#xff0c;共计33篇&#xff1a; 有需要的小伙伴关注我&#xff0c;点击在看&#xff0c;并私信回复“技战法”…