Day_19 多线程基础

PrintStream/PrintWriter
PrintStream/PrintWriter :  输出流 -> 打印字节输出流/打印字符输出流

PrintStream :  System.out系统标准输出流的对象类型
	特殊的输出方法: println(任意类型的对象);

PrintWriter : 兼容性很强
	自动刷新和自动换行 :
		自动刷新: 必须在创建PrintWriter对象时打开自动刷新的开关,并且输出数据的方法必须使用 println(),printf(),format()
		自动换行: 输出时必须调用println()
    //总结 : 既要自动刷新又要自动换行必须打开刷新开关和调用println方法进行数据的输出!!
            
构造方法:
	PrintWriter(String fileName) : 直接传入目标文件地址;//不能设置自动刷新的开关
	PrintWriter(File file) : 传入File对象;
	
	//转换流,包装流
	PrintWriter(OutputStream out) : 既可以接收字节流对象;
    PrintWriter(Writer out) : 也可以接收字符流对象;
    
	//带有自动刷新开关的构造方法
    PrintWriter(OutputStream out, boolean autoFlush) 
    PrintWriter(Writer out, boolean autoFlush)  
        
PrintWriter(String fileName)构造的源代码:
	//this(Writer out, boolean autoFlush)
	this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
             false);

PrintWriter(Writer out)构造的源代码:
	///this(Writer out, boolean autoFlush)
	this(out, false);


写的方法:
	//PrintWriter一定具备普通字符输出流写数据的五种写法
	特殊的写方法 :
		void println(任意类型的对象) : 输出并换行
		void print(任意类型的对象) : 输出不换行
		
趣味案例:创建一个超级流对象
	把基本流: FileOutputStream 封装成一个具有 : 自动刷新,自动换行,追加写,设置写的编码方式的高效字符流
		追加写: FileOutputStream/FileWriter
		自动刷新,自动换行 :  PrintWriter
		设置写的编码方式 : OutputStreamWriter
		高效流 : BufferedWriter
		
	PrintWriter pw = new PrintWriter(new BufferedWriter(
            	new OutputStreamWriter(
            	new FileOutputStream("目标文件地址",true/*追加写*/),"编码格式"/*设置编码格式*/)),true/*自动刷新开关*/);

请添加图片描述

Properties
Properties: 双列集合 -> 它和IO流之间有非常便捷的操作方法

注意事项:
	1. 创建Properties对象时,不可以给泛型; 因为父类把泛型写死了(Properties的泛型是<Object,Object>)
    2. 要实现和IO流交互的便捷方法,必须要求Properties集合中键和值的数据类型 必须是 String 类型
    
构造方法:
	Properties 集合名 = new Properties();

增删改查:HashMap的方法一样
	替换put方法 : Object setProperty(String key, String value)  
    替换get方法 : String getProperty(String key)  
    替换keySet方法 : Set<String> stringPropertyNames()  
        
Properties 和IO 交互的方法:
	一键把集合中的内容存储到文件中 : 
			void store(OutputStream out,String comment)
            void store(Writer out,String comment)    
	一键把文件中的属性集加载到集合中
			void load(InputStream in)  
            void load(Reader in)   
进程和线程
进程 : 正在执行的应用程序
线程 : 线程存在于进程中,一个进程至少有一个线程
并行和并发
并行: 在同一时刻有多个事情一起发生
并发: 在同一时间段有多个事情一起发生

多线程的程序是并行还是并发?
    多线程的程序即是并行也是并发
    
CPU如何同时运行多个程序的呢?
   1. 收集这些程序所有的线程,打散!
   2. 让线程抢夺CPU执行权,抢到了就执行 (随机)
线程的体系结构

请添加图片描述

线程的第一种开启方式(继承)
1. 创建一个类,继承Thread2. 重写父类中的run方法 -> 自己编写线程对象的任务
3. 创建子类的对象,并调用start()方法启动线程
线程的第二种开启方式(实现)
Thread类中的构造方法:
	Thread(Runnable target) 

1. 准备一个Runnable接口的实现类对象(拿类实现/匿名内部类) ,重写run方法   
2. 创建Runnable的实现类对象
3. 创建Thread类对象并把Runnable的实现类对象传递进去
4. 启动线程
线程执行的内存图

请添加图片描述

线程的第三种开启方式(有结果的线程任务)
Callable<V> 接口 -> 线程的任务接口  V: 线程完成任务后,结果的数据类型
	有且仅有一个方法: V call()
        
中间类 : FutureTask
	FutureTask(Callable<V> callable) 
	FutureTask(Runnable runnable, V result) 
    
类和接口之间的关系:
	1. Runnable接口 是 FutureTask 的父接口
	2. FutureTask(Callable<V> callable) 
    3. Thread(Runnable target)
    
1. 创建Callable<V>的实现类对象,重写call方法编写线程的任务
2. 创建FutureTask对象,并把任务对象传递给FutureTask对象
3. 创建Thread对象,并把FutureTask对象传递给Thread对象
4. 线程对象调用start方法,启动线程

FutureTask类中的V get()方法 : (阻塞方法)
	获取线程执行完毕后的结果,必须要等到线程执行完毕后返回结果才执行!
线程的名称设置和获取方法
线程对象名的设置:
	1. 构造方法:
		Thread(String name) 
        Thread(Runnable target, String name) 
	2. 成员方法:
		 void setName(String name)  
             
获取线程对象的名称:
	Thread类中的成员方法: String getName()
        
 //若不能直接调用getName(),可以先使用Thread类中的静态方法:
        static Thread currentThread(): 获取当前线程对象
线程的优先级
线程的默认优先级 : 5
线程的最小优先级 : 1
线程的最大优先级 : 10
//优先级越高的线程 优先执行的概率越大    

获取线程优先级的方法:
	 int getPriority() 
设置线程优先级的方法:
	 void setPriority(int newPriority) 
守护线程
 void setDaemon(boolean on) : 传入true 设置为守护线程
线程休眠的方法
static void sleep(long millis) : 让线程休眠 -> 休眠多久由传入的毫秒值决定

休眠 : 线程对象仅仅释放CPU的执行权,不释放锁资源
线程的安全问题
只要有多个线程同时操作共享数据的时候,一定可能出现线程安全问题!!!
    
    
火车站买票案例如何解决: 上锁    

同步操纵一定能解决所有多线程情况下的安全问题
同步操作
同步操作 : 就是上锁的意思

锁对象具备的特点:
	1. 唯一
	2. 能控制所有的线程对象
	3. 用于做锁的元素必须是引用数据类型 -> 优先推荐: Object
	
同步后的代码线程对象要执行必须:	
	1. CPU的执行权
	2. 锁资源
同步代码块
格式:
    synchronized(锁对象){
        //需要保护的代码
    }
同步方法
格式:
	方法的修饰符 synchronized 返回值类型 方法名(形参列表){
        方法体;
        //return;
    }

普通成员同步方法的锁对象是this
静态同步方法的锁对象是谁? 本类的字节码对象 .class对象
Lock接口(面向对象的方式上锁)
Lock接口中有2个方法:
	void lock(): 上锁
	void unlock(): 解锁
	
实现类 : ReentrantLock	
线程的生命周期
NEW : 新建 -> 线程对象创建出来了但是没有调用start
BLOCKED : 阻塞 -> 线程醒着但是没有锁资源或者没有CPU执行权
TIMED_WAITING -> 限时等待
	场景1 : 线程对象被调用了sleep(毫秒值) -> sleep: 仅仅丢失CPU执行权,拥有锁资源
    场景2 : 线程对象被调用了wait(毫秒值) -> wait: 丢失锁资源和CPU执行权
WAITING -> 无限等待
	场景 :  线程对象被调用了wait() -> 只有等待被唤醒才能从无限等待状态中复活
RUNNABLE : 运行 -> 拥有CPU执行权,拥有锁对象 正在执行的线程对象
TERMINATED : 死亡 -> 已经死亡的线程状态

请添加图片描述

等待和唤醒的方法
等待和唤醒的方法来自于 Object 类

一般都是使用锁对象控制线程的执行!!
    
唤醒方法: 只是唤醒线程,线程醒了还需要去抢夺CPU资源和锁资源
	void notify() : 随机唤醒一个"沉睡"的线程对象
 	void notifyAll() : 唤醒所有"沉睡"的线程对象
        
等待方法: wait : 释放锁和CPU资源
	void wait() : 无限等待 不被调用notify系列方法线程就不会醒  
    void wait(long timeout)  : 限时等待 时间到自己醒或者在中途被唤醒
    void wait(long timeout, int nanos)      
等待唤醒机制
等待唤醒机制/线程的通讯/生产者和消费者案例

顾客线程,厨师线程,包子类(锁对象,控制线程执行)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值