Java------多线程学习

news/2024/11/29 4:48:13/

Java线程学习总结

今天把Java多线程学习了一下,作如下总结

进程与线程

进程是程序关于某个数据集合的一次执行过程
线程是操作系统能够运算调度的最小单位,是进程中单一顺序的控制流
一个进程可以并发执行多个线程,进程是线程的容器

例如:电脑QQ,QQ是进程,发送消息,QQ空间就是线程

单线程

单线程,就是程序执行时,进程中的线程顺序是连续的

package ThreadExample;/*** @author cxw* @date 2022/4/30*/public class Singal_ThreadExample {//单线程演示//单线程,程序执行时,进程中的线程顺序是连续的public static void main(String[] args) {MyThread m1 = new MyThread("MyThread1");MyThread m2 = new MyThread("MyTHread2");m1.run();m2.run();//单线程的限制//m2调用run()方法,要等m1调用完了之后才可以继续调用//多线程可以实现上述结果交叉输出  多线程即进程可以并发执行//实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。}
}//单线程
class MyThread {String str;public MyThread(String str) {this.str = str;}void run() {for (int i = 0; i < 3; i++) {System.out.println("输入参数是: " + str);}}
}

多线程

多线程可以使单个程序内部在同一时刻执行多个代码段,完成不同的任务。一个复杂的任务可以分解为多个子任务交予线程执行,实现异步执行环境
多线程可以实现上述结果交叉输出 多线程即进程可以并发执行
例如,浏览器就是一个多线程的例子,可以浏览网页时同时播放声音和动画

多线程的实现方法

常用的两个,一是创建线程子类,继承Thread类;二是在定义的类中实现Runnable接口

创建Thread类的子类

创建一个类,继承Thread类并且重写其中的run()方法

package ThreadExample;/*** @author cxw* @date 2022/4/30*/public class MyThreadExample {//创建Thread类的子类来实现多线程static class Thread1 extends Thread {private String str = null;public Thread1(String str) {this.str = str;}//重写Thread中的run()方法public void run() {for (int i = 0; i < 3; i++) {System.out.println("你输入的是:" + str);try {//sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)//Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {Thread1 t1 = new Thread1("Thread1");Thread1 t2 = new Thread1("===============");Thread1 t3 = new Thread1("Thread2");t1.start();t2.start();t3.start();/*你输入的是:Thread1你输入的是:Thread2你输入的是:===============你输入的是:===============你输入的是:Thread1你输入的是:Thread2你输入的是:Thread1你输入的是:===============你输入的是:Thread2*/}
}

实现Runnable接口

Java不支持多线程,如果要继承Thread后就无法继承其他类,但是可以实现Runnable接口并且重写run()方法实现多线程

package ThreadExample;/*** @author cxw* @date 2022/4/30*/public class RunnableExample {//实现Runnablestatic class Mythread implements Runnable {private String str;public Mythread(String str) {this.str = str;}//重写run()方法@Overridepublic void run() {for (int i = 0; i < 3; i++) {System.out.println("你输入的是:" + str);try {//Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {Mythread t1 = new Mythread("MyThread1");Mythread t2 = new Mythread("MyThread2");Mythread t3 = new Mythread("============");//将目标对象传递给Thread实例Thread thread1 = new Thread(t1);Thread thread2 = new Thread(t2);Thread thread3 = new Thread(t3);thread1.start();thread2.start();thread3.start();}
}

实现多线程分别打印0~99的数字的功能

实现多线程分别打印0~99的数字的功能

package ThreadExample.Practice;/*** @author cxw* @date 2022/4/30*/public class Practice1 {static class MyThread extends Thread {private int num;public MyThread(int num) {this.num = num;}//重写Thread中的run()方法public void run() {//for (int i = 0; i < 100; i++) {System.out.println("num: " + num);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// }}}public static void main(String[] args) {for (int i = 0; i < 100; i++) {MyThread t1 = new MyThread(i);t1.start();}}
}

Runnable接口和Thread类的区别

两种方法都要执行start()方法来为线程分配系统资源,调度线程并且执行线程run()方法
当一个线程已经继承另一个类时,就应该使用Runnable接口来实现多线程

多线程的同步

如果一个程序激活了多个线程,并且多个线程共享同一资源,可能会发生冲突。这个时候就要使用进程的同步机制来解决
线程同步指的是通过特定的同步机制来控制多线程间的执行顺序,即使多个线程按照预定的先后次序执行

synchronized关键字

synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突

package ThreadExample;/*** @author cxw* @date 2022/4/30*/public class SameThread {//线程同步问题public static int count = 10;//synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突public static synchronized int buyTicket() {if (count <= 0) {return -1;   //无票}count--;System.out.println("剩余票数: " + count);return count;}public static void main(String[] args) {for (int i = 0; i < 15; i++) {new Thread() {public void run() {SameThread.buyTicket();}}.start();}}
}/* 未加同步锁
剩余票数: 3
剩余票数: 1
剩余票数: 9
剩余票数: 7
剩余票数: 2
剩余票数: 6
剩余票数: 8
剩余票数: 5
剩余票数: 0
剩余票数: 4*//*
加了同步锁
剩余票数: 9
剩余票数: 8
剩余票数: 7
剩余票数: 6
剩余票数: 5
剩余票数: 4
剩余票数: 3
剩余票数: 2
剩余票数: 1
剩余票数: 0*/

同步锁的例题

三个窗口同时售卖20张票

多线程同步锁的应用 三个窗口同时售卖20张票

package ThreadExample.PracticeExample;/*** @author cxw* @date 2022/4/30*/public class Example1 {//多线程同步锁的应用  三个窗口同时售卖20张票static class Sation extends Thread {public Sation(String name) {super(name);}static int count = 20;  //票数static Object object = "aa";   //创建一个同步锁 静态的钥匙//重写run方法public void run() {while (count > 0) {//使用一个锁, // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来synchronized (object) {if (count > 0) {System.out.println(getName() + "卖出了第 " + count + "张票!");count--;} else {System.out.println("票卖完了!");}}try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {Sation s1 = new Sation("站台1");Sation s2 = new Sation("站台2");Sation s3 = new Sation("站台3");s1.start();s2.start();s3.start();}
}/*
运行结果
站台1卖出了第 20张票!
站台3卖出了第 19张票!
站台2卖出了第 18张票!
站台1卖出了第 17张票!
站台3卖出了第 16张票!
站台2卖出了第 15张票!
站台1卖出了第 14张票!
站台3卖出了第 13张票!
站台2卖出了第 12张票!
站台1卖出了第 11张票!
站台3卖出了第 10张票!
站台2卖出了第 9张票!
站台1卖出了第 8张票!
站台3卖出了第 7张票!
站台2卖出了第 6张票!
站台1卖出了第 5张票!
站台3卖出了第 4张票!
站台2卖出了第 3张票!
站台1卖出了第 2张票!
站台3卖出了第 1张票!*/
银行取钱1

两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!

package ThreadExample.PracticeExample;
/*** @author cxw* @date 2022/4/30*/import java.util.Objects;public class Example2 {//两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!public static void main(String[] args) {Bank bank = new Bank();PersonA personA = new PersonA(bank, "ATM", "小明");PersonB personB = new PersonB(bank, "Counter", "小白");personA.start();personB.start();}}//银行类
class Bank {//账户的金额为1000static double money = 1000;//在柜台取钱public void Counter(double money) {this.money -= money;System.out.println("柜台取钱 " + money + "还剩 " + this.money);}//在ATM机取钱public void ATM(double money) {this.money -= money;System.out.println("ATM取钱 " + money + "还剩 " + this.money);}//提供一个对外取款的途径public synchronized void OutMoney(double money, String mode) throws Exception {if (money > this.money) {//检验余额是否充足throw new Exception("取款金额" + money + ",余额只剩" + this.money + ",取款失败!");}if (Objects.equals(mode, "ATM")) {ATM(money);} else {Counter(money);}}
}//创建一个人类,模拟取钱  继承自Thread类
class PersonA extends Thread {//哪个银行private Bank bank;//何种方式private String mode;//姓名private String name;public PersonA(Bank bank, String mode, String name) {this.bank = bank;this.mode = mode;this.name = name;}@Overridepublic void run() {while (bank.money >= 100) {try {bank.OutMoney(100, mode);} catch (Exception e) {e.printStackTrace();}try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}class PersonB extends Thread {//哪个银行private Bank bank;//何种方式private String mode;//姓名private String name;public PersonB(Bank bank, String mode, String name) {this.bank = bank;this.mode = mode;this.name = name;}@Overridepublic void run() {while (bank.money >= 200) {try {bank.OutMoney(200, mode);} catch (Exception e) {e.printStackTrace();}try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
银行取钱2

编写一个模拟银行存款的程序。假设有两个储户都去银行往同一账户存款,一次存100,每次存3次。要求储户每存一次前,账户余额增加100,并在控制台输出当前账户的余额。

package ThreadExample.Practice;/*** @author cxw* @date 2022/4/30*/public class Practice2 {public static void main(String[] args) {//进程同步锁的使用Bank bank = new Bank();Person a = new Person(bank);Person b = new Person(bank);Person c = new Person(bank);Thread t1 = new Thread(a);Thread t2 = new Thread(b);Thread t3 = new Thread(c);t1.start();t2.start();t3.start();}
}//银行类
class Bank {//账户的初始金额为1000static double money = 1000;//存钱的方法public void SaveMoney(double getMoney) {money += getMoney;System.out.println("柜台存钱 " + getMoney + ",总金额为 " + money);}
}//创建一个存钱的人类,模拟存钱
class Person implements Runnable {Bank bank;static Object object = "aa";  //创建一个同步锁public Person(Bank bank) {this.bank = bank;}//重写run()方法@Overridepublic void run() {//存到3000块停止存钱while (bank.money < 3000) {//同步锁  金额随存钱次数的增加而不同步改变synchronized (object) {try {bank.SaveMoney(100);} catch (Exception e) {e.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

欢迎大家指正,over
作者:爱吃水果的cc


http://www.ppmy.cn/news/676594.html

相关文章

第二章 Caché 服务器页面简介 - 你应该知道

文章目录 第二章 Cach 服务器页面简介 - 你应该知道你应该知道什么CSP SamplesCSP 文档 第二章 Cach 服务器页面简介 - 你应该知道 你应该知道什么 要高效使用 CSP&#xff0c;应该熟悉以下内容&#xff1a; Cach objects and ObjectScript HTML JavaScript SQL CSP Sam…

百度网盘免费高速下载(详细过程)

百度网盘加速器&#xff08;下载速度在8-9M/S&#xff09;&#xff08;BUG只针对首次使用用户能体验高速下载&#xff0c;需要使用新的账号才能一直体验&#xff09; 方法一&#xff1a; 百度网盘加速器小工具&#xff08;无需安装即可使用&#xff09; 下载地址&#xff1a…

android应用RxPermissions申请权限依赖添加方法和使用代码

android应用RxPermissions申请权限依赖添加方法和使用代码 环境&#xff1a;Android Studio2021.2&#xff0c;java添加依赖&#xff1a; 打开build.gradle(app),添加以下代码&#xff1a; implementation com.github.tbruyelle:rxpermissions:0.12 //rxJava 注意&#xff1a;…

解决m1的mac下 执行flutter pub run ffigen 出现“(have ‘arm64’, need ‘x86_64’)“错误

解决m1的mac下 执行flutter pub run ffigen 出现"(have ‘arm64’, need ‘x86_64’)"错误 ffigen主要是用来将底层的c/c的导出函数转成dart能方便调用的方法&#xff0c;用起来挺方便的&#xff0c;之前在windows弄成功过&#xff0c;现在在要在m1的mac下再弄一次&…

指数形式的傅里叶级数

傅里叶提出的两个重要的观点&#xff1a; 1.周期信号都可以表示为谐波关系的正弦信号的加权和&#xff08;傅里叶级数&#xff09; 2.非周期信号都可用正弦信号的加权积分表示&#xff08;傅里叶变换&#xff09; 参考上一篇博客 https://blog.csdn.net/Chevy_cxw/article/det…

SQL慢?吐血整理MySQL中Explain分析工具

前言 当我们遇到一条SQL慢的时候&#xff0c;往往需要使用一些性能分析工具&#xff0c;看看这个SQL究竟是为什么慢&#xff1f;那本文就分享MySQL中的一个性能分析神器——Explain, 通过读懂它的结果&#xff0c;我们可以知道SQL的执行计划&#xff0c;也就是具体执行查询的方…

在ubuntu16.04下安装opencv3.4.5(超详细)

一、编译安装 1.官网下载sources版本(For Linux)&#xff1a;http://opencv.org/releases.html 2.解压&#xff1a; unzip opencv-3.4.5.zip3.进入&#xff1a; cd opencv-3.4.5&#xff08;如果安装的文件在本机上&#xff0c;则先进入此安装包所在路径&#xff0c;比如我的…

keras 搭建lstm+dnn网络 多步时间序列预测 模板

# -*- coding: utf-8 -*- # 导入库pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn import metrics from sklearn.metrics import mean_square…