第五周的学习

第二十天

Map集合

Interface Map<k,v> key 键 value 值

Map接口下面 已经封装好实现类

--|HashMap

--|TreeMap

Map接口下面的方法

增:
    V   put(K key, V value)
    将指定的值与该映射中的指定键相关联(可选操作)。
    void    putAll(Map<? extends K,? extends V> m)
        将指定地图的所有映射复制到此映射(可选操作)。
删:
    V remove(K  key);  通过键删除指定的值  返回值是被删除的值
改:
    V put(K key, V value)  当键没有的话,就是添加,没有的话,就是覆盖
查:
    int size();  查看集合中的元素的个数
    boolean isEmpty(); 判断集合是否为空
    boolean containsKey(Obejct Key);  判断集合中是否包含这个键
    boolean containsValue(Obejct value);  判断集合中是否包含这个值
    
    重要的方法:
    V get(K key);  通过键获取值
    Set<K> keySet()  获取所有的键存到set集合中
    Collection<V>   values()   获取所有集合中的值
    Set<Map.Entry<K,V>> entrySet()  将键值对 的map的实体存到set集合中
    

File类

相对路径:

得有一个参照物

./ 代表的是当前的工作目录

../上一级目录

../../上两级目录

../../../上三级目录

绝对路径:

从磁盘的跟目录一直到文件的所在位置

C:\aaa\3.txt

File构造方法

File(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File(String parent, String child)
static String`  `separator`与系统相关的默认名称 - 分隔符字符

File类下面的方法

boolean createNewFile(); 新建一个文件

1.如果文件路径不存在, 系统找不到指定的路径

2.如果文件已经存在 返回一个false

3.磁盘坏了

boolean mkdir(); 创建单级的目录

boolean mkdirs();创建多级的目录

删除文件或者文件夹

boolean delete();

File类下面判断的方法

boolean isFile();是否是文件

boolean isDirectory(); 是否是文件夹

boolean isHidden(); 是否是隐藏文件

boolean isAbsolute(); 是否是绝对路径

boolean exists(); 文件或者文件夹是否存在

获取方法 返回值的是字符串的方法

String getName();获取文件或者文件夹的名字的

STring getParent();获取上一级目录

String getPath();获取file对象的绝对路径

方法是long类型数据

long length();获取文件占用磁盘的字节数

long lastModified(); 获取当前文件修改的时间 时间戳

获取当前文件夹下面的所有的文件

File[] listFiles();

String[] list();

递归

一句话来概括:

一个方法自己多次调用自己,但是得有结束的条件

例如:删除某一个目录下面的所有文件

package com.qf.d_digui;
​
import java.io.File;
​
​
public class Demo3 {
    public static void main(String[] args) {
        File file = new File("c:/bbb");
        del(file);
    }
    public static void del (File file) {
        //找到bbb文件夹下面所有的文件和文件夹
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) {//如果是文件夹 就继续执行del方法
                del(file1);
            } else {//不是文件夹
                file1.delete();
​
            }
        }
    }
}
​

第二十一天

IO流

以后会遇到 上传和下载 等这些需求。

I input 输入

O output 输出

缓冲的概念

计算机通过cpu读取硬盘的数据,在Java中可以加上缓冲的概念,每次读取具体的缓冲值。可以提高效率

IO流

从磁盘(c盘)读取数据到内存(Java代码) 1.txt====》java代码(输出出来)

输入流:

input :场景使用 从磁盘的c:/aaa/1.txt文件中 读取数据 到内存中(Java代码)

字节输入流

字符输入流

从内存(Java代码 String="狗蛋")写入数据到 磁盘(c盘 1.txt)

输出流:

output : 从内存(String str = " 还是数据库的借口借口") 写入到磁盘的c:/aaa/1.txt文件中

字节输出流:

字符输出流

参照物体 是内存

字节传文件案例:

package com.qf.a.test;
​
import java.io.*;
​
//5、编写一个程序,将d:\java目录下的a.txt文件复制到d:\jad目录下。
public class Demo1 {
 public static void main(String[] args) throws IOException {
     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("D:/java/a.txt")));
     BufferedOutputStream bof = new BufferedOutputStream(new FileOutputStream(new File("D:/java/jad/sb.txt")));
     byte[] buf = new byte[1024];
     int length;
     while ((length=bis.read(buf))!=-1) {
         bof.write(buf,0,length);
     }
     bof.close();
     bis.close();
 }
}
​

字符的案例:

package com.qf.f_zonghe;
​
import java.io.*;
​
​
public class Demo1 {
 public static void main(String[] args) throws IOException {
     //字符流将一个文本赋值2到另外一个文件夹下面
     //BufferedReader  专门将文本内容读取到内存中
     BufferedReader br = new BufferedReader(new FileReader("c:/bbb/《雪中悍刀行》.txt"));
     BufferedWriter bw = new BufferedWriter(new FileWriter("c:/aaa/88.txt"));
     char[] cbuf= new char[1024];
     int length;
     while ((length = br.read(cbuf)) != -1) {
         bw.write(cbuf, 0, length);
     }
     bw.close();
     br.close();
 }
}
​

总结

总结:
    1.输入流和输出流的功能
        输入流:  从磁盘到内存(Java代码)
        输出流:  从内存(java 代码)到磁盘
    2.输入流
        分为两种:
            字节输入流
                FileInputSrteam 
            字符输入流
                FileR4
                核心方法:  read
                
            关于效率问题,他们两个有对应的缓冲流
                FileInputSrteam 对应的BufferedInputStream
                FileReader 对应的 BufferedReader
    3.输出流
        分为两种:
            字节输出流:
                FileOutputStream
            字符输出流:
                FileWriter
                    核心的方法 write
            关于效率问题,他们两个有对应的缓冲流
            FileOutputStream对应的缓冲流 BufferedOutputStream 
            FileWriter对应缓冲流   BufferedWriter
    4.记住一句话 用字节流    

序列化和反序列化

从内存到磁盘 序列化 输出流 ObjectOutputStream write

package com.qf.g_serialize;

import java.io.*;
import java.util.ArrayList;

class Employee implements Serializable {
    String name;
    int age;
    transient int ID;//短暂的  此属性不可序列化
    String adress;//地址

    public void eat() {
        System.out.println("今天中午没有吃饱");
    }
}

public class Demo1 {
    public static void main(String[] args) throws IOException {
        ArrayList arrayList = new ArrayList();
        Employee employee = new Employee();
        employee.name = "gousheng";
        employee.adress = "航海中路";
        employee.age = 18;
        employee.ID = 8989;
        //将Java代码中的对象存到磁盘中
        FileOutputStream fos = new FileOutputStream("c:/aaa/emp.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(employee);
        oos.close();
        fos.close();

    }
}

反序列化 从磁盘到 内存中 inputStream

package com.qf.g_serialize;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.ObjectInputStream;


public class Demo2 {
    public static void main(String[] args) throws Exception {
        //反序列化
        FileInputStream fis = new FileInputStream("c:/aaa/emp.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Employee emp = (Employee)ois.readObject();
        System.out.println(emp.name);
        System.out.println(emp.age);
        System.out.println(emp.adress);
        System.out.println(emp.ID);//0

    }
}

第二十二天

StringBuffer

线程安全 , 可变的字符序列

方法:

package com.qf.a_stringbuffer;


public class Demo1 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdef");
        System.out.println(sb);
        //System.out.println(sb.toString());//将StringBuffer类型的数据转为String
        sb.append("a");//追加   abcdtrue
        sb.insert(2, "狗");
        //ab狗cdefa
        sb.delete(2, 4);//abdefa
        //字符串反转
        System.out.println(sb.reverse());//afedba
        System.out.println(sb);
        System.out.println(sb.capacity());//容量 容量是新插入字符可用的存储量
        StringBuffer sb1 = new StringBuffer();
        System.out.println(sb1.capacity());//16
        sb1.append("12345678912345671");
        System.out.println(sb1.capacity());







    }
}

枚举类

Java中有一个特殊的类叫枚举类,一般表示的是常量。

语法格式:

public enum 枚举类名 {
	各组常量,常量之间使用逗号隔开
}

枚举方法:

values();  枚举类中的所有的值
oridnal();每个常量的索引值
valueOf();返回值的指定的字符串的常量
package com.qf.b_enum;


enum SexEnum {
    MALE(0, "男"),
    FEMALE(1, "女"),
    ;
    private int sex;//0代表男 or 1  代表女
    private String sexName;//男 or 女

    SexEnum(int sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }

    public int getSex() {
        return sex;
    }

    public String getSexName() {
        return sexName;
    }
}
class User {//用户类
    private String name;//用户名字
    private SexEnum sex;//用户的性别

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public SexEnum getSex() {
        return sex;
    }

    public void setSex(SexEnum sex) {
        this.sex = sex;
    }
}
public class Demo6 {
    public static void main(String[] args) {
        User user = new User();
        user.setName("狗蛋");//赋值
        user.setSex(SexEnum.MALE);

        System.out.println(user.getSex().getSexName());



    }
}

包装类

Java八大基本数据类型,都有与之对应的包装类

int==>Integer

byte===>Byte

short====>Short

long====>Long

float====>Float

double====>Double

boolean====>Boolean

char====>Character

【重点】:

1.自从jdk5之后 ,有自动拆箱和自动装箱

自动装箱: 将基本数据类型转为包装类类型

自动拆箱: 将包装类转为基本数据类型

 		2. static String    toString();  将基本数据类型转为 字符串
           		3. static  parse***(); 将一个字符串转为 所对应基本数据类型

Math

Math类包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。

Math的方法:

Math.abs(); //求一个数的绝对值
Math.max(a,b);  //  求两个数最大值的
Math.min(a,b);  //  求两个数最小值的
Math.ceil(a);//向上取整
Math.floor(a);//向下取整
Math.round(a);//四舍五入
Math.random();//double   大于等于 0.0 ,小于 1.0 。

Random

package com.qf.e_random;

import java.util.Random;

public class Demo1 {
    public static void main(String[] args) {
        Random random = new Random();
        System.out.println(random.nextInt());
        System.out.println(random.nextBoolean());
        System.out.println(random.nextInt(3));
        System.out.println(random.nextDouble());
    }
}

System

System类提供的System包括标准输入,标准输出和错误输出流; 访问外部定义的属性和环境变量; 一种加载文件和库的方法; 以及用于快速复制阵列的一部分的实用方法。

package com.qf.f_system;

import java.io.PrintStream;
import java.util.Properties;
import java.util.Scanner;


public class Demo1 {
    public static void main(String[] args) {
        PrintStream out = System.out;//标准输出
        out.println("hehe");
        System.out.println("xiix");
        Scanner scanner = new Scanner(System.in);
        //m	err
        //“标准”错误输出流。
        System.err.println("haha");

        //返回当前的时间
        long l = System.currentTimeMillis();   //ms
        System.out.println(l);//1680076586166
        //在1970年1月1日UTC之间的当前时间和午夜之间的差异,以毫秒为单位。

        //通过类 获取当前系统的一个属性
        Properties properties = System.getProperties();
        System.out.println(properties.get("os.name"));//Windows 10
        System.out.println(properties.get("user.name"));//bowang
        System.out.println(properties.get("java.version"));//1.8.0_241
    }
}

Date

专门处理时间的一个类

package com.qf.g_date;

import java.text.SimpleDateFormat;
import java.util.Date;


public class Demo1 {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
        //Wed Mar 29 16:17:57 IRKT 2023
        //我难受 看不懂? 吧咋办? 转成你能看懂的   格式化
        //SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期
        //SimpleDateFormat(String pattern)
        //使用给定模式 SimpleDateFormat并使用默认的 FORMAT语言环境的默认日期格式符号。
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = sdf.format(date);
        System.out.println(format);
    }
}
package com.qf.g_date;

import java.util.Calendar;
import java.util.Date;


public class Demo2 {
    public static void main(String[] args) {
        Date date = new Date();
        //返回一个值,该值是从包含本开始时间的年份中减去1900的值
        System.out.println(date.getYear() + 1900);
        //返回一个数字,表示包含或开始于此Date对象所代表的时刻的月份 。 返回的值在0和11之间,其值为0代表一月。
        System.out.println(date.getMonth() + 1);//2


        //返回由此日期表示的星期几。 返回值( 0 =星期日, 1 =星期一, 2 =星期二, 3 =星期三, 4 =星期四, 5 =星期五, 6 =星期六)表示包含或以此时间表示的时刻开始的星期几Date对
        System.out.println(date.getDay());//3

        Calendar rightNow = Calendar.getInstance();//获取日历的对象
        System.out.println(rightNow);

        System.out.println(rightNow.get(Calendar.YEAR));//2023
        System.out.println(rightNow.get(Calendar.MONTH) + 1);//3
        System.out.println(rightNow.get(Calendar.DAY_OF_MONTH));//29
        System.out.println(rightNow.get(Calendar.DAY_OF_YEAR));//88
        System.out.println(rightNow.get(Calendar.DAY_OF_WEEK) - 1);//4
        System.out.println(rightNow.get(Calendar.HOUR));//4  pm
        System.out.println(rightNow.get(Calendar.HOUR_OF_DAY));//16





    }
}

第二十三天

进程

是一个独立的运行应用程序

  1. 独立性

    各个进程之间是互相独立的,互相不影响的。

  2. 互斥性

    每个应用程序(软件) 系统分配一个独立的端口号如果一个软件qq端口号 97 idea端口也叫97

线程

进程是由至少一个或者多个线程组成的。

线程是进程最小的基本单位。

1.抢占式运行【重要】

给程序 分配CPU,按照时间片来执行,单位时间片抢占式执行的。随机抢占的

2.资源共享

同一个进程,有多个线程,这个多个线程是可以共享同一个数据的

Java程序:Demo1可以看成一个进程,

一个Java程序中有两个线程:

1.main 主线程

2.垃圾回收的线程

面试题: 进程和线程区别

1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程

的资源。

4、系统开销:在创建或撤销进程的时候,由于系统都要为之分配和回收资源,导致系统的明显

大于创建或撤销线程时的开销。但进程有独立的地址空间,进程崩溃后,在保护模式下不会对其

他的进程产生影响,而线程只是一个进程中的不同的执行路径。线程有自己的堆栈和局部变量,

但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多

线程的程序健壮,但是在进程切换时,耗费的资源较大,效率要差些。

并行和并发

并行: 真正的同时执行

并发: 同时发生,轮流交替执行

创建线程的两种方式

Java虚拟机允许应用程序同时执行多个执行线程。

创建线程的第一种:

创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写run方法Thread 。 然后可以分配并启动子类的实例。

第二种创建方式:

另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

第一方式:  继承Thread

第二种方式: 实现Runnable接口

线程方法

构造方法:

Thread()

分配一个新的 Thread对象。

Thread(Runnable target)

分配一个新的 Thread对象。 第二种创建的形式

Thread(Runnable target, String name)

分配一个新的 Thread对象。并对这个线程起一个名字

方法:

static ThreadcurrentThread()返回对当前正在执行的线程对象的引用。
StringgetName()返回此线程的名称。
voidsetName(String name)将此线程的名称更改为等于参数 name
Thread.currentThread();//获取当前线程对象
getNeme();  获取当前线程的名字

线程下面的方法:

intgetPriority()返回此线程的优先级。
voidsetPriority(int newPriority)更改此线程的优先级。

还是抢占,结果不可预期

static voidsleep(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

线程同步和锁

当多个线程同时请求一个数据的时候,会导致数据不准确的情况。相互之间产生问题。容易出现线程安全的问题。比如多个线程操作同一个数据,都打算修改商品库存。

线程的同步真实的意思: 让你"排队",几个线程之间要排队。一个一个对共享资源进行操作,等一个结束以后,另外一个再进来操作。变量 是唯一的和准确的

可以加锁

package com.qf.d_thread;



class SaleTicket implements Runnable {
    private  int ticket = 100;
    @Override
    public  void run() {

        while (true) {

            synchronized (this) {

                if (ticket > 0) {

                    //线程2卖出了第72票
                    //线程2卖出了第71票
                    //线程1卖出了第100票
                    //线程1   线程2 都进入到if语句了
                    //
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket +"票");

                    ticket--;
                } else {
                    System.out.println("卖完了");
                    break;
                }
            }
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //强调的是:多个线程操作同一个数据  ticket
        SaleTicket saleTicket = new SaleTicket();

        new Thread(saleTicket, "线程1").start();
        new Thread(saleTicket, "线程2").start();
    }
}

Java中的锁

synchronized 被成为隐式锁,会自动释放,式一个非公平的锁。

Lock锁 被成为显示锁。

他们两个锁都可以解决线程同步的问题。但是synchronized 更加强大,更加粒度化。更加灵活。

所以一般开发时候用synchronized 。以后还会有线程池,也有锁 更高级。

Lock是一个接口,实现ReentrantLock

有两个重要方法:

lock();

unlock();

package com.qf.d_thread;

import java.util.concurrent.locks.ReentrantLock;

class SaleTicket1 implements Runnable {
    private int ticket = 100;
    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {

        while (true) {
            try{


                lock.lock();
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "票");

                    ticket--;
                } else {
                    System.out.println("票已经买完了");
                    break;
                }
            } catch (Exception e) {

            } finally {
                lock.unlock();
            }


        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        //强调的是:多个线程操作同一个数据  ticket
        SaleTicket1 saleTicket = new SaleTicket1();

        new Thread(saleTicket, "线程1").start();
        new Thread(saleTicket, "线程2").start();
    }
}

守护线程【了解】

守护线程是用来守护非守护线程的

package com.qf.d_thread;


class MyThread8 implements  Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("守护线程:" + i);
        }
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.isDaemon());//false  非守护线程
       // thread.setDaemon(true);//设置为守护线程
        Thread thread1 = new Thread(new MyThread8());
        //System.out.println(thread1.isDaemon());
        thread1.setDaemon(true);
        thread1.start();
        for (int i = 0; i < 200; i++) {
            System.out.println("主线程:" + i);
        }


    }
}

第二十四天

死锁

开发中禁止出现死锁

面试会问:

应用场景: 并发场景,多个线程。线程之间在共享数据的时候 是互不相让的

线程加锁为了线程安全,但是物极必反。

死锁是一种状态,当两个线程互相持有对象所需要的资源的时候,这两个线程又都不主动释放资源

就会导致死锁。代码无法正常执行。这两个线程就会僵持住。

Object类下面的和线程相关的方法

public final void wait()
             throws InterruptedException

导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。

总结: 至少两个线程, 对象.wait() ,那么当前线程就会等待。

package com.qf.b_object;
​
​
//为啥写Message这个类?  wait方法    对象.wait(); 创建Message对象
    //
class Message {
    private String message;//信息
​
    public Message(String message) {
        this.message = message;
    }
​
    public void setMessage(String message) {
        this.message = message;
    }
​
    public String getMessage() {
        return message;
    }
​
}
//线程类  等待线程
class WaitThread implements Runnable {
    private Message message;
​
    public WaitThread(Message message) {
        this.message = message;
    }
//等待线程抢到了
    //等待线程睡了5秒  然后唤醒线程执行。  synchronized (message)
    //message  对象从等待池中国去取的,结果发现没有  阻塞
    //回到等待线程睡醒了以后开始   wait等待
​
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + "正在等待中....");
​
        synchronized (message) {
            try {
​
                //当调用wait方法的时候,会自动释放锁,并将对象放到等待池中,让唤醒线程锁来操作这个对象
                //
                message.wait();//代码走到这一步 当前线程会等待!!!
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name +"被唤醒!!!Line45行的");
            System.out.println(message.getMessage());
        }
    }
}
//唤醒线程
class NotifyThread implements Runnable {
    private Message message;
​
    public NotifyThread(Message message ) {
        this.message = message;
    }
    @Override public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("唤醒线程已经执行");
       synchronized (message) {
            message.setMessage("我是修改之后的message对象");
            //message.notify();
            message.notifyAll();
​
       }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Message message = new Message("我是message对象");
        WaitThread waitThread = new WaitThread(message);
        WaitThread waitThread1 = new WaitThread(message);
        NotifyThread notifyThread = new NotifyThread(message);
​
        new Thread(waitThread1, "wait2线程").start();
        new Thread(waitThread, "wait1线程").start();
        new Thread(notifyThread, "notify线程").start();
​
    }
}
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值