javaSE多线程,IO流

本文详细讲解了多线程的基本概念、线程创建的两种方式(继承Thread和实现Runnable接口)、线程池的使用、线程同步与线程状态,以及Java中的锁机制。涵盖了Thread类、线程优先级、代理设计模式和死锁解决。
摘要由CSDN通过智能技术生成

多线程

线程进程

线程依赖于进程存在,进程能够独立的调用系统资源---->通过系统资源操作底层数据(c语言)
线程--->能够执行的最小单元,多个线程会同时并发的去访问一些数据
线程的执行具有随机性!

创建线程的三种方式

提供Thread类第一种创建线程的方式
      1)自定义一个类 继承的自Thread类
      2)重写Thread类的run方法---->完成一些的耗时的操作
      3)在main用户线程中,创建当前这个类对象
      4)开启线程---->不是run方法,run方法它只是一个普通方法(仅仅执行线程里面的内容:读文件/完成io的操作....)
       启动线程start()--->jvm是调用run线程的方法,结果是两个同时执行(具有随机性)
       
public class MyThread extends  Thread{
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+" - "+i);
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MyThread my = new MyThread();
        my.start();
    }
}
多线程的创建方式2:
  	 1)自定义一个类实现Runnable接口,
 	  2)实现接口里面的run方法--->完成耗时操作
  	 3)在main用户线程中创建当前这个类的实例--->"资源类对象"
  	 4)创建线程类Thread对象,然后将3)资源类对象 作为参数传递,启动线程!
  	 
public class ThreadTest {
    public static void main(String[] args) {
        MyRunnable ru = new MyRunnable();
        Thread th1 = new Thread(ru);
        th1.start();
    }
}
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+" - "+i);
        }
    }
}
线程池:
       会创建一些固定的可重复使用的线程数,会在线程池中,循环利用
 当某些线程使用完毕,不会被释放掉,而是归还连接池中,等待下一次再去利用!
 
  成本比普通创建线程方式要大!
  java.util.concurrent.Exceutors 工厂类
       public static ExecutorService newFixedThreadPool(int nThreads)
       创建固定的可重复的线程数的线程池
  java.util.concurrent ExecutorService ----->接口的具体实现类 public class ThreadPoolExecutor
       <T> Future<T> submit(Callable<T> task):提交异步任务,返回值就是异步任务计算的结果;
      上面这个的返回值Future :异步计算的结果---如果现在只是看多个线程是否能够并发的去强转CPU执行权,并没有返回结果
      这个返回值可以不用返回!
      Callable:接口---->异步任务的执行  类似于 之前Runnable接口
 
       void shutdown():关闭线程池
public class MyCallable implements Callable<Integer> {
    private Integer a;
    public MyCallable(Integer a){
        this.a = a;
    }

    @Override
    public Integer call() throws Exception {
        for(int x = 1; x <=a ; x++){
            a+=x;
            System.out.println(Thread.currentThread().getName()+":"+a) ;
        }
        return a;
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Integer a = 100;
        Future<?> submit = es.submit(new MyCallable(a));
        try {
            Object o = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        es.shutdown();

    }
}

Thread的方法
   启动线程,想知道哪一个线程执行数据---Thread类提供一些基本功能:
   public final void setName(String name):设置线程的名称
   public final String getName():获取线程名称
   public final void join() throws InterruptedException 等待该线程终止
   public static void yield():暂停当前正在执行的线程,执行其他线程
   线程的优先级:
   public static final int MAX_PRIORITY 10  最大优先级
   public static final int MIN_PRIORITY 1   最大优先级
   public static final int NORM_PRIORITY 5  默认优先级
   优先级越大,线程抢占CPU执行权的几率越大!

   给线程设置优先级
        public final void setPriority(int newPriority)
   获取线程的优先级
        public final int getPriority()

线程的状态有几种?

6种状态
Thread类的内部枚举: State
			NEW---新建
			RUNNABLE---运行
			BLOCKED---阻塞
			WAITTING ---死死等待 本质调用wait(0)
			TIMEDWAIITING---超时等待
			TERMINATED---终止(死亡状态)
		

代理设计模式

   代理核心思想:
               真实角色专注自己的事情(开发中,针对自己的业务)
               代理角色帮助真实完成一件事情
   静态代理
               代理角色和真实角色要实现同一个接口

死锁

使用synchronized解决线程安全问题,安全问题解决了,效率低,可能死锁现象
 	两个线程出现了一种互相等待的情况,A线程等待B线程释放锁,B线程等待A线程释放锁,造成死锁现象!
 	解决死锁问题--->线程之间的通信必须使用的同一个资源!  (生产者和消费者模式思想)

排序

TreeMap<K,V>-->针对键有效,排序(自然排序/比较器排序)
  构造方法:
       public TreeMap():自然排序
       public TreeMap(Comparator<? super K> comparator):比较器排序
 
   如果键是自定义类型,键必须唯一,而且需要有排序规则!
 
   TreeSet<引用类型,String> 来按照学生的年龄从小到大排序(主要条件)
public class Demo {
    public static void main(String[] args) {
        TreeSet<Worker> ts = new TreeSet<>(new Comparator<Worker>() {
            @Override
            public int compare(Worker o1, Worker o2) {
                int n = o1.getAge()-o2.getAge();
                int m = (n==0)?(o2.getName().compareTo(o1.getName())):n;
                return m;
            }
        });

        ts.add(new Worker("xiaoming",9));
        ts.add(new Worker("xiaowang",23));
        ts.add(new Worker("wangwu",20));
        for(Worker w:ts){
            System.out.println(w.getName()+"--"+w.getAge());
        }
    }
}
public class Worker {
    private String name;
    private int age;

    public Worker() {
    }

    public Worker(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Worker worker = (Worker) o;
        return age == worker.age && name.equals(worker.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Lock

  Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作
   实现类:
           可重入的互斥锁 java.util.concurrent.locks.ReentrantLock
 
           获取锁:指定的某个时刻   public void lock()
           释放锁 : public void unlock()
       Lock l = ...;
       l.lock();
       try {
           // access the resource protected by this lock
       } finally {
                l.unlock();    //释放锁(系统相关的资源)
       }

Timer计时器

java.util.Timer:定时器(可以执行一次或者重复执行某个任务)
    构造方法:
           Timer():创建一个计时器
    成员方法
       public void cancel()取消定时器
       void schedule(TimerTask task, Date time)  :在给定的日期时间来执行TimerTask定时任务  ---> String dataStr = "2022-11-22 18:00" ;//---->日期文本---->java.util.Date
            (应用场景:引入使用io流的方式,在指定时间点上,删除指定带内容的目录里面的所有.java文件)
 
       void schedule(TimerTask task, long delay)  :在给定多少毫秒后(延迟时间)执行这个定时任务
       public void schedule(TimerTask task,long delay,long period):在指定延迟时间(delay)执行任务,
       然后每经过固定延迟时间(period)重复执行任务
 
       schedule这些方法第一个参数都是定时任务:TimerTask是一个抽象类,
       1)可以定义具体的子类继承自TimerTask
       2)直接可以使用抽象类的匿名内部类

递归

方法递归:
           1)需要有方法
           2)有一定规律
           3)有方法结束的条件(出口条件),否则 "死递归"
 
          构造方法没有递归

java.io.File:高级功能

  public String[] list():抽象路径名表示的目录中的文件和目录。
  boolean accept(File pathname):
               抽象路径名称所表示的路径是否放在File列表中,取决于返回值 true,否则false,不放在列表中
 public File[] listFiles(FilenameFilter filter):获取指定抽象路径表示下的所有的File数组,获取File数组的时候,就可以通过文件名称过滤器按照条件进行过滤
       FilenameFilter接口
               boolean accept(File dir,String name) :参数1:指定的目录
                    参数2:文件名称
                    返回值: true,将指定指定目录下的文件放在File列表中;否则false
public class FileTest {
    public static void main(String[] args) {
        File f = new File("D:\\");
        File[] files = f.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                File f = new File(dir, name);
                return f.isDirectory();
            }
        });
        if (files!=null) {
            for (File fi : files) {
                System.out.println(fi);
            }
        }
    }
}
IO流分类
      1)按流的方向划分
           输入流     ---->读
           输出流     ---->写
      2)按流的类型划分--同时按方向划分:
           字节流
              字节输入流:InputStream--->不能实例化--->具体的子类:针对文件的字节输入流 FileInputStream
              字节输出流:OutputStream--->不能实例化--->具体的子类:针对文件的字节输出流 FileOutputStream
 
              字节缓冲流(字节高效流)
              字节缓冲输入流:BufferedInputStream
              字节缓冲输出流:BufferedInputStream
           字符流
              字符输入流
              字符输出流

在这里插入图片描述

public FileOutputStream(String name,boolean append) throws FileNotFoundException 创建字节文件输出流对象,实现文件的末尾追加,而不将之前覆盖,第二个参数必须为true
字节输入流:InputStream--->读 抽象类
提供子类:FileInputStream:针对文件操作的字节输入流
  1)创建文件字节输入流对象
  2)读文件
           public int read() throws IOException:一次读取一个字节,返回字节数
           public int read(byte[] b) throws IOException:一次读取一个字节数组
  3)释放资源
  使用基本字节流一次读取一个字节数组:
  	public int read(byte[] b) throws IOException:一次读取一个字节数组
字节缓冲输出流/输入流 (高效字节流)
  	BuffedOutputStream/BufferedInputStream:只是提供一个字节缓冲区,本身就是一个字节数组,不会直接操作文件
  	操作具体的文件使用都是基本字节流FileInputStream/FileOutputStream
 
 	 public BufferedOutputStream(OutputStream out):创建一个字节缓冲输出流对象,默认缓冲区大小(足够大)
  	 public BufferedInputStream(InputStream in):创建一个字节缓冲输入流对象,默认缓冲大小
字符流是在字节流后出现,如果是文本文本进行操作,优先使用字符流!
字符流
       Writer:具体的子类
               public OutputStreamWriter(OutputStream out):
               字符转换输出流(可以将基本字节输出流转换成字符输出流),平台默认的字符集编码(idea,utf-8)
               public OutputStreamWriter(OutputStream out,String charsetName):
                      字符转换输出流 ,指定一个编码字符集
 
               写的功能
      void write(char[] cbuf)写入一个字符数组。
      abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
      void write(int c)  写一个字符
      void write(String str)写一个字符串
      void write(String str, int off, int len) :写入字符串的一部分

      Reader:抽象类
               具体子类
               public InputStreamReader(InputStream in):创建字符转换输入流,以平台默认字符集解码
               public InputStreamReader(InputStream in,String  charsetName):
                               创建字符转换输入流对象,指定字符集解码
 
               read的功能
                       public int read(char[] cbuf):读取字符数组
                       public int read():读一个字符
      InputStreamReader/OutputStreamWriter:字符转换流弊端:代码格式复杂,不能直接操作文件!
 
BufferedReader(Reader in):字符缓冲输入流
   也可以键盘录入
 
          main()里面String[] 可以键盘录入 ,录入字符串
          Scanner以及提供的nextXXX()
          BufferedReader
          BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
  	他们不能直接操作文件,提供缓冲区让读写效率更高,特有方式
BufferedReader一次读取一行/可以作为键盘录入(录入一行字符串内容)
 
字符流针对文本文件(记事本打开能看懂的)-->字符流读写复制
  	1)字符转换流InputStreamReader/OutputStreamWriter 一次读取一个字符/一次读取一个字符数组
  	2)使用字符转换流的便捷类FileReader/FileWriter 可以直接操作文件 一次读取一个字符/一次读取一个字符数组
  	3)使用字符缓冲流BufferedReader/BufferedWriter: 一次读取一个字符/一次读取一个字符数组
  	4)使用字符缓冲流BufferedReader/BufferedWriter :一次读取一行特有方式(推荐!)
  读写复制

Properties

Properties类表示一组持久的属性。
  	Properties可以保存到流中或从流中加载。(重要的地方)
  	属性列表中的每个键及其对应的值都是一个字符串。
 
  	继承Hashtable---->实现Map接口---->存储数据,取出数据----都可以使用Map的方式
  构造方法:
       public Properties():创建空的属性列表
 java.util.Properites属性列表有自己的遍历方式---底层基于Map实现的
       添加元素:
               public Object setProperty(String key, String value)
       遍历属性列表
               public Set<String> stringPropertyNames()获取属性列表中的所有的键
               public String getProperty(String key)使用此属性列表中指定的键搜索属性
               Properties特有方式
  		public void load(Reader reader)throws IOException :
  将指定文件中的内容加载属性集合列表中(内容键值对 key=value)
 
 	 	void store(Writer writer, String comments)  :将属性列表中的内容保存指定文件中(以"键=值"元素对进行保存)
              第一个参数:字符输出/使用字节输出流
              第二个参数:属性列表的描述
       读取src路径下的properties文件
       		InputStream inputStream = Test3.class.getClassLoader().
                getResourceAsStream("name.properties");
        		将输入流对象的内容加载属性列表中
        		prop.load(inputStream);

throw和throws的区别

1)抛出的位置不同
	throws抛出在方法声明上
	throw抛出在方法体中
2)后面使用异常格式不同
	throws 后面跟的异常类名,而且中间逗号隔开,可以抛出多个异常
	throw 后面跟的异常对象 new XXXException() ;跟的具体的某一个异常对象
3)处理异常方式不同
	针对带有throws的方法,异常处理是交给调用者处理!
	针对throw抛出异常的处理,交给方法体中逻辑语句处理! 举例 
		if(条件表达式){
        	thrwo new XXException();
         }
 4)是否抛出的异常的肯定性
 		throws:表示抛出异常的可能性,执行某段代码,可能出现问题
 				String的日期文本---->java.util.Date格式---->解析parse  (通过SimpleDateFormat)
 				"2022-11-24"
 	    throw:表示抛出异常的肯定性,执行方法体中某段代码,一定会出现异常!	
为什么wait()和notify(),线程等待,线程唤醒为什么定义Object类中?
    这些方法都是和锁对象有关系,而锁对象可以是任意Java类对象,而定义Object类中
    调用 wait(),会立即释放锁!
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值