关于java学习笔记(一)


笔记

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.



    }
}


StringBuilderStringBuffer

//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 关键字给方法加上内置锁来实现线程安全
常见的:HashTableStringBufferVector

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中用于处理数据流的一种方式,它允许程序对数据进行读取和写入。(先进先出)
核心抽象类:
InputStreamOutputStream:分别代表字节输入流和字节输出流,是所有字节流的基类。
ReaderWriter:分别代表字符输入流和字符输出流,是所有字符流的基类。
常用类:
FileInputStreamFileOutputStream:用于文件的读写操作。
BufferedInputStreamBufferedOutputStream:通过缓冲区提高读写效 率。

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

线程同步

线程同步是一种在多线程环境中协调线程对共享资源访问的机制。目的是为了防止多个线程同时对同一份数据进行操作,从而避免数据不一致和程序出错。

线程同步的作用:

  1. 保证数据一致性:确保对共享数据的修改能够按照预期的顺序进行,避免数据被意外覆盖。

  2. 避免竞态条件:竞态条件是指程序的最终结果依赖于多个线程的执行顺序。线程同步可以确保线程按正确的顺序执行,防止竞态条件的发生。

  3. 提高程序的可预测性:在没有同步的情况下,线程的执行顺序是不确定的,这会导致程序行为难以预测。线程同步可以控制线程的执行顺序,使程序的行为更加稳定和可预测。

如何实现线程同步

  1. 互斥锁:确保一次只有一个线程能够进入临界区(访问共享资源的代码段)。
  2. 信号量:一种计数器,用来记录可用的资源数量。线程在访问资源前需要先获取信号量,访问后再释放。
  3. 原子操作:使用特殊的CPU指令,保证某些操作在多个线程看来是“不可分割”的,即要么完全执行,要么完全不执行。
  4. 消息传递:线程之间通过发送和接收消息来协调彼此的行为,而不是直接访问共享资源。

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);//使用对象实例的方法来调用
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值