文章目录
笔记
2024/3/19
关于昨天的一些重点
1、八大基本数据
byte,int,short,long,float,double,boolean,char
2、输入
Scanner scanner = new Scanner(System.in);//快速new一个,alt+回车在回车
int a = scanner.nextInt();
关于对下午内容的总结
1、equals()
判断对象是否与参数一样(类似与==)
System.out.println(str.equals("abcd"));//结果是true或false
但不能判断基本数据类型,这是错的:
int x=20,y=30;
System.out.println(x.equals(y));
具体原理为什么还是不太清楚(网上说是比较引用数据类型的对象,基本数据类型的包装类https://www.runoob.com/java/java-number.html)
补充:
基本数据类型:存放数据值
引用数据类型:存放的是地址,数据值在其他空间
如果想用数值,可以使用:
Integer integer = new Integer(12);
System.out.println(integer.equals(12));
2、String()
与其他数据类型不一样,可以有如下的表示:
String string = new String("abcd");
String str = "abcd";
3、三目运算
System.out.println(3>2?true:false);//结果为true
4、运算符
右移: << -----每次加自己的一倍,4<<3------8,16,32
左移: >> -----每次减自己的一半,24>>3-----12,6,3
&&: 同真为真
int a=12,b=23;
System.out.println((a>b)&&(b>a));//false
|| : 同假为假
! : 非
^ : 异或,仅有一个为true,结果才true
5、if(){}else{}
6、while(),do{}while
7、for(;😉{}
8、switch(){case : ;break;default: ;}
如找到对应的case,但后面没有break时,匹配成功后,从当前 case 开始,后续所有 case 的值都会输出。如果后续的 case 语句块有 break 语句则会跳出判断。
2024/3/20
类和对象
类:从对象中抽象出来的共同特征
public class Dog {
//属性;
//方法;
}
//new
Dog dog = new Dog();
构造方法(成员变量初始化类)
当new时候会调用默认的构造方法,若以定义则不会使用默认的
public class Dog {
String breed;
int size;
String colour;
int age;
public Dog(){//与类名完全一样
size=13;
colour=red;
}
public Dog(int i){//与类名完全一样
i=size;
colour=red;
}
//一个类可以有多个构造方法。
}
//调用
数组
int[] arr={12,23,34,23,12,11};
int[] ints = new int[]{12,12,12};
int[] ints1 = new int[4];
//二维数组,数组里面存放一维数组
int[][] ints1 = new int[][]{{},{}};
方法
public static void main(String[] args){}//主方法
//方法为程序的最新执行单元
//定义一个
public static void myText(){}
myText();//调用即可
2024/3/21
字符串
String,创建之后不可改变内容
String str1 = "abcd";
//new
String str2 = new String();
//字符数组
char[] chs = {'a','b','c','d','e'};
//Ascii码
Byte[] bt = {97,98,99};
StringBuilder(),创建字符串可以改变内容
提供方法
StringBuilder stringBuilder = new StringBuilder("abcd");
stringBuilder.append('e');//在后面添加e
stringBuilder.reverse();//反转字符串
stringBuilder.length();
String str = stringBuilder.toString();//变回字符串
集合ArrayList(),长度可自动变化
ArrayList<String> list = new ArrayList<String>();
//限定数据类型String
//不能存放八大基本数据类型,只能放保障类
list.add("abcd");//增
list.remove('b');//删
list.set(1,"w");//改
list.get(1);//查
2024/4/1
类与对象
类:抽象的一种东西
基础语法:
public class person{
//人的类
//属性与方法
String name;
int age;
public void eat(){
//1、无参无返回
}
//我们也可已写
//2、无参有返回
//3、有参无返回
//4、有参有返回
}
对象:对类进行实例化
person persons = new perspn();//实例化
//调用属性和方法
persons.name = "张三";
persons.age = 17;
persons.eat();
基础语法就是上述的这些,重要的是灵活的使用,有待提高
2024/4/3
构造方法
格式
public 类名(){
}
有参或者无参
重载
用来丰富方法的行为,有点意思
值传递
基本数据类型传递是值
引用数据类型传递是地址
String比较特殊,传递的也是值
作用域
全局变量都可以用,局部变量只能在局部用喽,如下:
public class Text {
public static void main(String[] args) {
int x;
for (int i = 0; i < 10; i++) {
}
//我可以用x,但我用不了i
}
}
2024/4/6
封装:
狭义上对安全性考虑,private修饰属性,要是没有set和get就不能访问,但有点纳闷感觉没啥大用
广义是对义务的封装,使动作方法进行普遍适用性
以打印数据这个动作为例:
public class Print<T> {
public void printBase(T[] resout){
if (resout[i]!=null){
//目前只能一个一个写,待优化
if (resout[i] instanceof User){
//用户
User uu = (User) resout[i];
System.out.println(uu.id+"\t\t\t"+uu.name);
}else if (resout[i] instanceof Menu){
//菜单
Menu mm = (Menu)resout[i]; System.out.println(mm.id+"\t\t"+mm.name
+"\t\t"+mm.prise);
}else{
//other
}
}
}
}
//主程序在new时候注意,T需要写成数据类型,如下:
Print<User> userPrint = new Print<User>();
userPrint.printBase(uus);
2024/4/10
对昨天内容的总结
1、修饰符
常用的只有private和public,作用是清楚的
2、static
被他修饰的属性或方法(不能修饰构造方法)会被全局共享,就相当于只要修改,那么不管在哪使用都是修改后的值。
想如果在其他类使用,代码如下:
public class Demo1 {
static int;
}
//在其他类中使用
public class Demo2 {
Demo1.id;//即可
}
//调用方法都是一样的
3、继承
关键字:extends
可以继承非私有是属性和方法,
但是不能继承:
1、私有的属性和方法
2、static修饰的(但是可以直接调用)
3、构造方法(但可以使用,不过只能在儿子的构造方法在super()调用,而且只能是第一行,你在new一个儿子时,会先调用爸爸的构造在调用儿子的)
如果想有爸爸的属性方法super关键字,如果儿子与父亲有重名的,优先调儿子的,在儿子里面也可以用用this调自己
儿子只有唯一的爸爸,爸爸可以有多个儿子
2024/4/12
重写与重载
重写继承的基础上,发生在不同的类中,对方法进行重写,方法体不同其他的必须相同。
而重载则是在同个类中,名字一样,参数不同方法体也不同。
特征:1:方法名相同
2:参数列表相同。
3:返回值类型相同或者是其子类。
4:父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法。
5:子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法(注:静态方法中无法使用super).
6:父类的私有方法不能被子类覆盖。
7:不能抛出比父类方法更多的异常。
8:访问权限不能严于父类。
==和equals
equals:只能用于比较引用数据类型,用来比较地址,但是如果String类的话用来 比较值。
==:如果用来比较引用数据类型,比较的是地址。如果用来比较基本数据类型,比 较的是值。
多态
一个行为多种表现形态,重写是多态的基础。
抽象类与抽象方法
抽象方法:被继承的某个类的某个方法,被重写了,原方法可能不会被使用了,我们可以用abstract来修饰这个方法,变成抽象类,便于解决代码的冗余。
抽象类:因为有了抽象类才导致需要抽象方法来装
特征:
1:抽象方法必须出现在抽象类中。
2:抽象方法必须在子类中被重写,除非子类也是一个抽象类。
3:抽象方法没有方法体。
4:抽象类中可以有非抽象方法。
5:抽象类不被实例化。
抽象类和普通类区别:
1:抽象类不能被实例化,普通类可以吧。
2:抽象类有抽象方法,普通类没有。
3:抽象类中的抽象方法,必须别子类重写,普通类方法不需要。
2024/4/13
接口
接口:纯粹版本的抽象类,或者说是抽象类的特殊的应用场景的实 现。
关键字:声明一个接口类interface ,某实现类用implements 来继承接 口类(可以多继承),而接口类可以继承(extends)其他接口。
抽象类vs接口:
相同点:
代表系统的抽象层。
都不能被实例化。
都能包含抽象方法。
不同点:
在抽象类中可以为部分方法提供默认实现,而接口中只能包含 抽象方法。
抽象类便于复用,接口便于代码维护。
一个类只能继承一个直接的父类,但可以实现多个接口。
2024/4/15
异常
关键字:
try{
}catch{
}finally
以及throw和throws
2024/4/17
API
api俗称接口,这个词出现在很多地方,tpc-c接口,摄像头接口
等等,而我现在提的是java的接口
interface :这是最初自己编写的时候写的接口,属于自产自销
javaAPI:java提供了许多接口
集合框架
集合框架Api:—>擅长存储引用数据类型,解决容器问题,解决数组带来的问题。
Collection接口:存储一组不唯一,无序的对象。
(1)、List: 接口存储一组不唯一,有序(插入顺序)的对象.
(1-1)ArrayList:实现了长度可变的数组,在内存中分配连续的 空间。遍历元素和随机访问元素的效率比较高
(1-2)LinkedList:采用链表存储方式,插入、删除元素时效率 比较高。
(1-3)Vector:实现了长度可变的数组,在内存中分配连续的空 间。实现了线程安全
Set:接口存储一组唯一,无序的对象引用
HashSet: 采用哈希列表存储,底层是由hashMap实现的
2024/4/18
package com.company.Day12;
import java.util.*;
public class Demo1 {
public static void main(String[] args) {
//键值对
//key唯一性
Map map = new HashMap();
map.put("1","zs");
map.put("2","li");
//打印数据(获取所有的值然后打印)
//注意,遵循先进后出的原则(压栈)
Collection values = map.values();
for (Object obj:
values) {
System.out.println(obj.toString());
}
//获取值
map.get("1");
//改
map.put("1","adag");//也可以当作修改
Object assa = map.replace("1", "assa");
//删除
map.remove("1");
//删除
map.remove("1");
//----------------------泛型-------------
Map<String,String> map1 = new HashMap<>();
map1.put("zs","123");
Set<String> strings = map1.keySet();
for (String obj:
strings) {
System.out.println(strings.toString().equals("zs"));
}
ArrayList<String> strings1 = new ArrayList<>();
strings1.add("ass");
ArrayList<ArrayList> arrayLists = new ArrayList<>();
arrayLists.add(strings1);
arrayLists.get(0).get(0);
User user = new User();
ArrayList<User> users = new ArrayList<>();
}
}
2024/4/19
枚举
//可以写任何东西
public enum NumClass {
工程师,
架构师
}
System.out.println(NumClass.架构师);
2024/4/22
随机数
package com.company.Day14;
import java.util.Random;
public class Demo1 {
public static void main(String[] args) {
//随机数
Random random = new Random();
//生成0-1之间double和float
double r1 = random.nextDouble();
float r2 = random.nextFloat();
//生成int之间整数
int r3 = random.nextInt();
//生成范围0-10
int r4 = random.nextInt(10);
//生成10-100
int r5 = random.nextInt(90)+10;
//还有一种是Math的
System.out.println(Math.random());
}
}
String和Arrays工具
String 类提供了许多用于字符串操作的方法,包括:
length():返回字符串的长度。
charAt(int index):返回指定索引处的字符。
substring(int beginIndex) 和 substring(int beginIndex, int endIndex):返回字符串的子串。
equals(Object another) 和 equalsIgnoreCase(String another):比较两个字符串是否相等。
startsWith(String prefix) 和 endsWith(String suffix):检查字符串是否以特定前缀或后缀开始或结束。
indexOf(int ch) 和 lastIndexOf(int ch):返回字符或子串在字符串中的位置。
replace(char oldChar, char newChar) 和 replaceAll(String regex, String replacement):替换字符串中的字符或匹配正则表达式的子串。
toLowerCase() 和 toUpperCase():将字符串转换为全小写或全大写。
trim():去除字符串两端的空白字符。
package com.company.Day14;
import java.util.Arrays;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
//字符串
//基本表示
String str1 = "abcdefg";
String str2 = new String("abcdefghijk");
//一些常用的方法
//获取字符
char c = str1.charAt(0);
//获取0-5子串,不包括6
String str3 = str1.substring(0,6);
//返回有木有子串起始下标,没有-1
int i = str1.indexOf("bc");
//若参数是数字,对应ascii码
int i1 = str1.indexOf(98);
//从第4个位置之后的开始查看
int i2 = str1.indexOf('a',3);
//从后往前查
int i4 = str1.lastIndexOf("bc");
byte[] bytes = str1.getBytes();//bit,ascii码
char[] chars = str1.toCharArray();//字符数组
//转大写
String str4 = str1.toUpperCase();
//按c进行分割,ab和def,不包括c
String[] strings = str1.split("c");
//Arrays工具,操作数组;
int[] ints = new int[10];
Arrays.fill(ints,10);//全部初始化未10
int[] ints1 = new int[]{2,5,9,6,1};
Arrays.sort(ints1);
Arrays.toString(ints);
//copy前3个
int[] ints2 = Arrays.copyOf(ints1,3);
ints2 = Arrays.copyOfRange(ints1,2,3);//copy2-3,但不包括3
Arrays.
}
}
StringBuilder
和 StringBuffer
//StringBuffer线程安全的类
append():向字符串添加字符或对象的字符串表示。
insert():在指定位置插入字符或字符串。
delete():删除指定范围内的字符。
replace():用另一个字符串替换指定范围内的字符。
substring():返回字符串的子串。
reverse():反转字符串。
toString():返回字符串的最终形式。
Date
public class Demo3 {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");
System.out.println(simpleDateFormat.format(date));
}
}
2024/4/23
线程安全
通过synchronized
关键字给方法加上内置锁来实现线程安全
常见的:HashTable
,StringBuffer
,Vector
IO:一组有序的序列,先进先出
输入输出流
注意喽,在new的时候,需要throws Exception
File file = new File("E:\\我的文件\\北大青鸟\\JAVA\\src\\com\\company\\Day14\\zsy.txt");
boolean exists = file.exists();//查看是否有这个文件
boolean file1 = file.isFile();//是不是文件
boolean directory = file.isDirectory();//是不是文件夹
String path = file.getPath();
// boolean delete = file.delete();
// boolean newFile = file.mkdirs();
//FileInputStream读出
FileInputStream fileInputStream = new FileInputStream(file);
int num = 0;
while ((num=fileInputStream.read())!=-1){
System.out.print((char) num);
}
fileInputStream.close();
//FileOutputStream写入,会覆原来的数据
//当文件txt不存在时,该方法会自动创建一个这个文件
OutputStream outputStream = new FileOutputStream(file,true);
String str = "你好,世界";
byte[] bytes = str.getBytes();
outputStream.write(bytes);
outputStream.close();
2024/4/24
字符流
代码冗余,代码复用
字符流:
Reader:
InputStreamReader–>FileReader:字符输入流
BufferedReader:字符输入流,带有缓冲区,可以成行的读取。
read();读
readLine():只能读取行支付串。
lines():返回Stream流,可以直接读取所有的行
Writer:
OutputStreamWriter–>FileWriter:字符输出流
BufferedWriter:字符输出流,带有缓冲区,可以成行的读取。
newLine():换行。
write():写入
public class Demo1 {
public static void main(String[] args) throws Exception {
String str = "E:\\我的文件\\北大青鸟\\JAVA\\src\\com\\company01\\Day15\\test.txt";
FileInputStream fileInputStream = new FileInputStream(str);
Reader reader = new InputStreamReader(fileInputStream);
char[] chars = new char[100];
int num = -1;
while ((num=reader.read(chars))!=-1){
}
for (int i = 0; i < chars.length; i++) {
if (chars[i]!=0){
System.out.print(chars[i]);
}
}
}
}
public class Demo4 {
public static void main(String[] args) throws Exception {
String str = "E:\\我的文件\\北大青鸟\\JAVA\\src\\com\\company01\\Day15\\test.txt";
FileInputStream fileInputStream = new FileInputStream(str);
Reader reader = new InputStreamReader(fileInputStream);
// char[] chars = new char[fileInputStream.available()];
BufferedReader bufferedReader = new BufferedReader(reader);
String s = bufferedReader.readLine();
System.out.println(s);
Stream<String> lines = bufferedReader.lines();
lines.forEach(x-> System.out.println(x));
}
}
关于IO一些知识的整理
Java I/O(输入/输出)流是Java中用于处理数据流的一种方式,它允许程序对数据进行读取和写入。(先进先出)
核心抽象类:
InputStream 和 OutputStream:分别代表字节输入流和字节输出流,是所有字节流的基类。
Reader 和 Writer:分别代表字符输入流和字符输出流,是所有字符流的基类。
常用类:
FileInputStream 和 FileOutputStream:用于文件的读写操作。
BufferedInputStream 和 BufferedOutputStream:通过缓冲区提高读写效 率。
InputStream
//InputStream 是 Java 中表示字节输入流的最高父类。
//InputStream 是 BufferedInputStream(间接) 和 FileInputStream 的共同基类。
String path1 = "E:\\我的文件\\北大青鸟\\JAVA\\src\\com\\company01\\Day14\\zsy.txt";
File file1 = new File(path1);
//创建
InputStream fis = new FileInputStream(path1);//可以传file或者path
//操作单个字节
//创建一个 BufferedInputStream(强化) 对象时,你需要提供一个已经存在的 InputStream 实例
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
OutputStream
FileOutputStream fos = new FileOutputStream("example.txt")
BufferedOutputStream bos = new BufferedOutputStream(fos)
Reader
//重要的子类
//BufferedReader - 继承自 Reader,是 Reader 的缓冲区包装器,提供了更高效的字符读取操作。
//InputStreamReader - 继承自 Reader,用于将字节流转换为字符流,它使用指定的字符集解码字节。
//FileReader - 继承自 Reader,用于从文件中读取字符
//FileReader 是从 Reader 类继承而来的,用于读取字符流。
Reader reader = new FileReader(file);//可以传file或者path
//操作单个字符
//BufferedReader又需要reader的实例(强化,可以操作行)
BufferedReader bufferedReader = new BufferedReader(reader);
//如果需要将 InputStream->Reader 转换为字符流,可以使用 InputStreamReader,它继承自 Reader,可以将字节流转换为字符流。
//FileInputStream 充当桥梁的作用,需要实例
InputStream fileInputStream = new FileInputStream(file);
Reader reader = new InputStreamReader(fileInputStream);
Writer
//Writer 的子类,如 FileWriter、BufferedWriter、PrintWriter 等
FileWriter writer = new FileWriter(...)//file或者path
Stream流
List<String> list = Arrays.asList("Java", "Kotlin", "Scala", "Groovy");
Stream<String> stream = list.stream(); // 从集合创建 Stream
String[] array = {"Java", "Kotlin", "Scala", "Groovy"};
Stream<String> streamFromArray = Arrays.stream(array); // 从数组创建 Stream
//参数选择
//1. 无参数的 Lambda 表达式:
() -> System.out.println("Hello, World!");
//2. 单个参数且可推断类型的 Lambda 表达式:
s -> System.out.println(s);
//3. 多个参数的 Lambda 表达式:
(int x, int y) -> x + y;
//4. 使用代码块作为 Lambda 体:
(String s1, String s2) -> {
return s1.compareTo(s2);
}
//常见的 Stream 操作:
//1. 过滤(filter) - 通过一个谓词筛选元素。
stream.filter(s -> s.startsWith("J")).forEach(System.out::println);
2024/4/29
二进制数据
//DataInputStream
//DataInputStream-->FilterInputStream(抽象)-->InputStream(抽象)
String str = "";
InputStream inputStream = new FileInputStream(str);
DataInputStream dataInputStream = new DataInputStream(inputStream);
//DataOutputStream
OutputStream outputStream = new FileOutputStream(str1);
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
序列化与反序列化
序列化:将对象的状态信息转换为可以存储或传输的格式
反序列:存储或传输的格式的数据转换回对应的 Java 对象
//实现 Serializable 接口:要序列化一个类,该类需要实现 Serializable 接口。
public class MyClass implements Serializable {
private static final long serialVersionUID = 1L;
// 类成员
}
//使用 ObjectOutputStream 进行序列化
OutputStream outputStream = new FileOutputStream("obj.txt");
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject(myObject);
//使用 ObjectInputStream 进行反序列化
InputStream inputStream = new FileInputStream("obj.txt");
ObjectInputStream ois = new ObjectInputStream(inputStream);
MyClass myObject = (MyClass) ois.readObject();//强转
线程与进程
进程(Process):进程就是程序的一次执行过程,是操作系统进行资源分配和保护的基本单位,程序是静态的,它作为系统中的一种资源是永远存在的。而进程是动态的,它是动态的产生,变化和消亡的,拥有其自己的生命周期。每个进程至少有一个线程,即主线程。
线程(Thread):线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程又称为迷你进程,但是它比进程更容易创建,也更容易撤销。进程作为资源分配单位和调度单位这两个属性分开处理,即进程还是作为资源分配的基本单位,但是不作为调度的基本单位(很少调度或切换),把调度执行与切换的责任交给线程,即线程成为独立调度的基本单位,它比进程更容易(更快)创建,也更容易撤销。
引入线程前,进程是资源分配和独立调度的基本单位。引入线程后,进程是资源分配的基本单位,线程是独立调度的基本单位。
引入多线程:
提高效率:多线程可以提高 CPU 利用率,允许同时执行多个任务。
改善响应时间:即使在执行长时间运行的任务时,程序也可以响应其他用户的输 入。
简化模型:多线程允许程序在单一进程内并行执行,简化了程序设计。
多线程也会带来一系列问题,如线程安全、死锁、资源竞争等。
并行与并发
并发(Concurrency):并发就是让多个任务看起来像是同时进行的,但实际上可能是快速地轮流进行。
并行(Parallelism):并行意味着真正的同时执行多个任务。如果你的电脑有多个CPU核心,那么它可以同时运行多个程序,每个核心处理一个程序,这样就能更快地完成任务。在单核处理器上,任务仍然会并发执行,但是操作系统会快速地在它们之间切换,给人一种并行的假象。
多线程
//----------创建-----------------
//继承 Thread 类:创建一个类继承 Thread 类,并重写 run() 方法。
public class MyThread extends Thread {
public void run() {
// 线程要执行的代码
}
}
// 在主程序中启动线程
MyThread t = new MyThread();
t.start();
//注意:调用start()方法时,你实际上是在请求JVM为这个线程对象创建一个新的执行线程。start()方法内部会调用run()方法。这意味着run()方法中的代码将在一个独立的线程中执行。
//如果直接调用run()方法( t.run(); )它的代码将会在主线程中顺序执行,而不会创建一个新的线程。
//实现 Runnable 接口:创建一个类实现 Runnable 接口,并实现 run() 方法。然后将该类的实例作为参数传递给 Thread 对象。
public class MyRunnable implements Runnable {
public void run() {
// 线程要执行的代码
}
}
// 在主程序中启动线程
Thread t = new Thread(new MyRunnable());
t.start();
//线程的生命周期
新建(New):当线程对象被创建,但 start() 方法尚未调用时,线程处于新建 状态。
可运行(Runnable):一旦 start() 方法被调用,线程就进入了可运行状态, 等待被操作系统的调度器选中并执行。
运行(Running):线程正在执行其 run() 方法中的代码。
阻塞(Blocked):线程因为等待同步资源(如锁)而暂停执行。
死亡(Dead):线程执行完毕或者因为异常退出了 run() 方法,此时线程结束 生命周期。
2024/4/30
线程同步
线程同步是一种在多线程环境中协调线程对共享资源访问的机制。目的是为了防止多个线程同时对同一份数据进行操作,从而避免数据不一致和程序出错。
线程同步的作用:
-
保证数据一致性:确保对共享数据的修改能够按照预期的顺序进行,避免数据被意外覆盖。
-
避免竞态条件:竞态条件是指程序的最终结果依赖于多个线程的执行顺序。线程同步可以确保线程按正确的顺序执行,防止竞态条件的发生。
-
提高程序的可预测性:在没有同步的情况下,线程的执行顺序是不确定的,这会导致程序行为难以预测。线程同步可以控制线程的执行顺序,使程序的行为更加稳定和可预测。
如何实现线程同步
- 互斥锁:确保一次只有一个线程能够进入临界区(访问共享资源的代码段)。
- 信号量:一种计数器,用来记录可用的资源数量。线程在访问资源前需要先获取信号量,访问后再释放。
- 原子操作:使用特殊的CPU指令,保证某些操作在多个线程看来是“不可分割”的,即要么完全执行,要么完全不执行。
- 消息传递:线程之间通过发送和接收消息来协调彼此的行为,而不是直接访问共享资源。
Java中实现线程同步
使用 synchronized
关键字和使用 java.util.concurrent.locks
包中的锁。
使用 synchronized
关键字:
1.同步方法:在方法声明中使用 synchronized
关键字,这样调用该方法的线程就会持有对象的锁。
整个方法都被视为一个监视器(Monitor)的临界区。这意味着同一时间只能有一个线程执行该方法。
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
2.同步代码块:在需要同步的代码块使用 synchronized
关键字,明确指定锁定的对象。
复制public void someMethod() {
synchronized (this) {
// 需要同步的代码
}
}
使用 java.util.concurrent.locks
包:
线程优先级
thread.setPriority(Thread.MAX_PRIORITY); // 设置线程优先级
线程等待
Thread.sleep(long millis)
:使当前线程暂停执行指定的毫秒数。Thread.yield()
:使当前线程让出对CPU的使用,允许线程调度器把CPU时间片分配给其他同优先级的线程。
线程加入
使用 join()
方法等待其他线程完成:
thread.join(); // 当前线程等待thread线程终止
锁的概念
在多线程环境中,锁是控制对共享资源访问的关键。当一个线程进入同步方法或代码块时,它会尝试获取该锁。如果锁已经被其他线程持有,那么该线程将阻塞,直到锁被释放。
线程通信
线程池
2024/6/11
反射机制
1、获取类模板
假设有个Test类,路径str=“src.Test”
Class<?> a=Class.forName(src);
Test.class;
new Test().getClass();
2、创建对象实例
Object o = a.newInstance();
3、获取属性使用属性
//假设,有
//public int id;
Field field = a.getField("id");//获取
field.set(o,2); //设置
4、获取方法使用方法
//假设,方法
//public void myMethod(String str,Int id){
//....
//}
Method method = clazz.getMethod("myMethod", String.class, int.class);//获取方法
Object result = method.invoke(o, "argumentString", 123);//使用对象实例的方法来调用
{
// 需要同步的代码
}
}
使用 `java.util.concurrent.locks` 包:
### 线程优先级
```java
thread.setPriority(Thread.MAX_PRIORITY); // 设置线程优先级
线程等待
Thread.sleep(long millis)
:使当前线程暂停执行指定的毫秒数。Thread.yield()
:使当前线程让出对CPU的使用,允许线程调度器把CPU时间片分配给其他同优先级的线程。
线程加入
使用 join()
方法等待其他线程完成:
thread.join(); // 当前线程等待thread线程终止
锁的概念
在多线程环境中,锁是控制对共享资源访问的关键。当一个线程进入同步方法或代码块时,它会尝试获取该锁。如果锁已经被其他线程持有,那么该线程将阻塞,直到锁被释放。
线程通信
线程池
2024/6/11
反射机制
1、获取类模板
假设有个Test类,路径str=“src.Test”
Class<?> a=Class.forName(src);
Test.class;
new Test().getClass();
2、创建对象实例
Object o = a.newInstance();
3、获取属性使用属性
//假设,有
//public int id;
Field field = a.getField("id");//获取
field.set(o,2); //设置
4、获取方法使用方法
//假设,方法
//public void myMethod(String str,Int id){
//....
//}
Method method = clazz.getMethod("myMethod", String.class, int.class);//获取方法
Object result = method.invoke(o, "argumentString", 123);//使用对象实例的方法来调用