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

多线程

并发执行的技术

并发和并行

并发:同一时间 有多个指令 在单个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的分配自动执行runm1.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{@Overridepublic void run() {for (int i = 0; i <10000000 ; i++) {System.out.println("1号线程");}}
}class My2 implements Runnable{@Overridepublic 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() {@Overridepublic void run() {for (int i = 0; i <10000000 ; i++) {System.out.println("1号线程");}}}).start();new Thread(new Runnable() {@Overridepublic 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() {@Overridepublic void run() {for (int i = 0; i <10000000 ; i++) {System.out.println("1号线程");}}});Thread t2=new Thread(new Runnable() {@Overridepublic 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() {@Overridepublic void run() {for (int i = 0; i <10000000 ; i++) {//Thread.currentThread()获取当前运行的线程对象//获取名字getName()System.out.println(Thread.currentThread().getName());}}});Thread t2=new Thread(new Runnable() {@Overridepublic 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{@Overridepublic void run() {for (int i = 0; i <100000 ; i++) {System.out.println(Thread.currentThread().getName());}}
}
class M2 implements Runnable{@Overridepublic void run() {for (int i = 0; i <100000 ; i++) {System.out.println(Thread.currentThread().getName());}}
}

休眠

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

class MM1 implements Runnable{@Overridepublic 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);//trueSingle 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 {@Overridepublic 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.mzph.cn/web/46407.shtml

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

相关文章

【.NET全栈】ASP.NET开发Web应用——站点导航技术

文章目录 前言一、站点地图1、定义站点地图文件2、使用SiteMapPath控件3、SiteMap类4、URL地址映射 二、TreeView控件1、使用TreeView控件2、以编程的方式添加节点3、使用TreeView控件导航4、绑定到XML文件5、按需加载节点6、带复选框的TreeView控件 三、Menu控件1、使用Menu控…

Hutool-Guava

目录 一、Guava 二、Hutool 三、区别与联系 四、使用场景 五、Guava工具类 1.集合工具类 2.字符串工具类 3.并发工具类 六、Hutool 1.字符串工具类 2.文件工具类 Hutool 和 Guava 都是 Java 开发中非常实用的工具库&#xff0c;它们提供了许多方便的工具类和方法&am…

字节抖音电商 后端开发岗位 一面

笔者整理答案&#xff0c;以供参考 自我介绍 项目&#xff08;20分钟&#xff09; RocketMQ延时消息的底层实现 回答&#xff1a; 延时消息的实现主要依赖于RocketMQ中的定时任务机制。消息被发送到Broker时&#xff0c;会先存储在一个特定的延时消息队列中。Broker会定时扫…

c++ extern 关键字

C中的extern关键字和跨语言互操作 变量的声明与定义 extern关键字用于声明在另一个翻译单元&#xff08;文件&#xff09;中定义的变量或函数。通过extern关键字&#xff0c;可以在多个文件中访问全局变量或函数。 变量声明示例 文件&#xff1a;main.cpp #include <io…

chatglm2-6b-prompt尝试

参考https://cloud.tencent.com/developer/article/2426296 chatglm2-6b&#xff0c;通过prompt来实现zero-shot/fewshot的自然语言处理任务 import json import re import os from modelscope.utils.constant import Tasks from modelscope import Model from modelscope.pi…

再议扩散模型

目录 一、基础知识 1、数学期望 2、概率表示 3、KL散度 二、扩散过程 三、理想的去噪过程 四、真实的去噪过程 五、噪声生成 导言 笔者早些时候曾粗略看过扩散模型的流程&#xff0c;但对于底层算法&#xff08;尤其是概率论方面&#xff09;&#xff0c;理解不够透彻…

pytorch学习(五)tensorboard使用

1. 创建环境 首先创建一个环境: conda create -n pytorch conda activate pytorch 然后安装tensorboard pip install tensorboard 安装opencv pip install opencv-python 2. 简单的案例 标量和图像的显示&#xff1a; 2.1标量实现的方法是add_scalar,第一个参数是给显…

探索Puppeteer的强大功能:抓取隐藏内容

背景/引言 在现代网页设计中&#xff0c;动态内容和隐藏元素的使用越来越普遍&#xff0c;这些内容往往只有在特定的用户交互或条件下才会显示出来。为了有效地获取这些隐藏内容&#xff0c;传统的静态爬虫技术往往力不从心。Puppeteer&#xff0c;作为一个强大的无头浏览器工…

印尼语翻译通:AI驱动的智能翻译与语言学习助手

在这个多元文化交织的世界中&#xff0c;语言是连接我们的桥梁。印尼语翻译通&#xff0c;一款专为打破语言障碍而生的智能翻译软件&#xff0c;让您与印尼语的世界轻松接轨。无论是商务出差、学术研究&#xff0c;还是探索印尼丰富的文化遗产&#xff0c;印尼语翻译通都是您的…

代码随想录算法训练营第三十六天|1049. 最后一块石头的重量 II 、 494. 目标和 、 474.一和零

1049. 最后一块石头的重量 II 分成两堆石头&#xff0c;一堆石头的总重量是dp[target]&#xff0c;另一堆就是sum - dp[target]。 在计算target的时候&#xff0c;target sum / 2 因为是向下取整&#xff0c;所以sum - dp[target] 一定是大于等于dp[target]的。 那么相撞之…

.NET C# 使用 iText 生成PDF

.NET C# 使用 iText 生成PDF 文章目录 .NET C# 使用 iText 生成PDF1 安装 iText 7 库&#xff1a;2 变量定义3 创建一个PDF4 段落5 旋转文本6 代码块7 外部链接8 内部链接9 表格10 注释11 线条12 二维码13 嵌入图像14 列表15 设置背景16 页眉17 页脚18 事件19 水印20 分栏21 源…

老古董Lisp(1):粗鲁先生Lisp再出发

粗鲁先生Lisp再出发 开始的原因 目标和梦想是最近考虑的一个问题。什么是目标&#xff1f;什么是梦想&#xff1f;梦想可以激励改变&#xff0c;目标才能实现改变。 开始这个部分的时候&#xff0c;我的梦想是什么&#xff1f;我的目标是什么&#xff1f;我想要什么&#xf…

libwebrtc.a+exosip连接fS 环境部署tips

//运行FS服务器 sudo ./freeswitch -nc -nonat //公网sudo ./freeswitch //运行客户端 sudo ./fs_cli //加载模块 load mod_av load mod_verto0.Invite交互过程 1.fs码率设置 2.用户密码改动 3.数字签名的摘要 4.FS收不到ACK 5.公网部署 6.查看frewswitch都占用哪些端口 7.日志…

Java(二十一)---栈的使用和模拟实现

文章目录 前言1.什么是栈(Stack)?2. 栈的模拟实现3.stack的使用![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/80c82d22f3ee49cfaa2915d1c961573e.png)4.关于栈的oj题4.1.有效的括号4.2.逆波兰表达式4.3.栈的压入、弹出序列4.4.最小栈 前言 前面几篇我们学习了顺序…

Vue--Router(路由)

目录 一 Router(路由) 1.作用 2.实现步骤 3.注意 一 Router(路由) 1.作用 Router又叫做路由&#xff0c;简单来说&#xff0c;就是用来实现vue的页面之间跳转的。 我们都知道&#xff0c;使用vue必然会涉及到很多个组件&#xff0c;也就是页面&#xff0c;而页面之间肯定需…

RK3588读取不到显示器edid

问题描述 3588HDMIout接老的显示器或者HDMI转DVI接DVI显示器显示不了或者显示内容是彩色条纹,但是这种显示器测试过如果接笔记本或者主机是可以直接显示的。这一类问题是HDMI下的i2c与显示器通讯没成功,读取不到设备的edid。问题包括全志的H3 、AML的S905都有遇到 测试环境…

Qt-事件与信号

事件和信号的区别在于&#xff0c;事件通常是由窗口系统或应用程序产生的&#xff0c;信号则是Qt定义或用户自定义的。Qt为界面组件定义的信号往往通常是对事件的封装&#xff0c;如QPushButton的clicked()信号可以看做对QEvent::MouseButtonRelease类事件的封装。 在使用界面组…

【QGroundControl二次开发】二.使用QT编译QGC(Windows)

【QGroundControl二次开发】一.开发环境准备&#xff08;Windows&#xff09; 二. 使用QT编译QGC&#xff08;Windows&#xff09; 2.1 打开QT Creator&#xff0c;选择打开项目&#xff0c;打开之前下载的QGC项目源码。 编译器选择Desktop Qt 6.6.3 MSVC2019 64bit。 点击运…

vue3-tree-org实现带照片的组织架构图

官方文档&#xff1a;vue3-tree-org 显示照片需要注意的地方 使用步骤 下载 npm install vue3-tree-org --save 在main.js中引入 import "vue3-tree-org/lib/vue3-tree-org.css"; import vue3TreeOrg from vue3-tree-org;app.use(vue3TreeOrg) 实现代码 <tem…

level 6 day2 网络基础2

1.socket&#xff08;三种套接字&#xff1a;认真看&#xff09; 套接字就是在这个应用空间和内核空间的一个接口&#xff0c;如下图 原始套接字可以从应用层直接访问到网络层&#xff0c;跳过了传输层&#xff0c;比如在ubtan里面直接ping 一个ip地址,他没有经过TCP或者UDP的数…