Java零基础(二十一)之多线程高级(二)+IO流初级

1.线程安全的HashMap

//ConcurrentHashMap: 并发的HashMap(前提是安全)
//Coolections中也提供了线程安全的Map,只不过锁的是整个hash表

public class Test1 {
    
    
	public static void main(String[] args) {
    
    
		Map<String, String> map = new ConcurrentHashMap<String, String>();
		for(int i=0;i<16;i++) {
    
    
			final int temp = i;
			new Thread(new Runnable() {
    
    
				@Override
				public void run() {
    
    
					map.put(Thread.currentThread().getName(), "value:"+temp);
					System.out.println(map);
				}
			}).start();
		}
	}
}

在这里插入图片描述

2.队列

2.1 Queue队列接口

//Queue:队列的接口,特点:先进先出
//LinkedList实现类就实现了该接口
public class Test1 {
    
    
	public static void main(String[] args) {
    
    
		Queue<Integer> queue = new LinkedList<Integer>();
		/*
		//如果没有元素,继续移除,会报异常
		queue.add(1);
		queue.add(3);
		queue.add(2);
		System.out.println(queue.element());  //取第一个元素
		System.out.println(queue.remove());   //取第一个元素,并移除
		*/
		
		
		//如果队列没有元素,则返回null--推荐
		queue.offer(1);
		queue.offer(3);
		queue.offer(2);
		
		System.out.println(queue.peek());  //取元素不移除
		System.out.println(queue.poll());  //取元素并移除
		System.out.println(queue);
	}
}

2.1 ConcurrentLinkedQueue实现类

//ConcurrentLinkedQueue: 在多线程中,性能最高的并发的队列
//内部采用了CAS无锁交换算法进行存储
//有3个参数:  V(要改变的变量)      E(预期值)      N(新值)
//执行过程中,如果V=E,那么N就可以改变V变量的值了

public class Test2 {
    
    
	public static void main(String[] args) throws InterruptedException {
    
    
		Queue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
		
		Thread th1 = new Thread(new Runnable() {
    
    
			
			@Override
			public void run() {
    
    
				for(int i=1;i<=5;i++) {
    
    
					queue.offer(i);
				}
			}
		});
		th1.start();
		
		Thread th2 = new Thread(new Runnable() {
    
    
			
			@Override
			public void run() {
    
    
				for(int i=6;i<=10;i++) {
    
    
					queue.offer(i);
				}
				
			}
		});
		th2.start();
		
		th1.join();  th2.join();
		

		
		for(int i=1;i<=10;i++) {
    
    
			System.out.println(queue.poll());
		}
		
		
	}
}


2.3 阻塞队列

//BlockingQueue:阻塞队列的接口
//实现类有: 有界队列ArrayBlockingQueue(推荐),无界队列LinkedBlockingQueue
//有界队列是有长度限制    无界队列可以认为没有
//有两个阻塞方法: put,take ,该阻塞方法的使用类似于生产者消费者用法
//put:一般不能超过有界队列长度,超过了阻塞       take,没有值时阻塞
public class Test3 {
    
    
	public static void main(String[] args) throws InterruptedException {
    
    
		BlockingQueue<String> queue = new ArrayBlockingQueue<String>(3);
		queue.put("苹果");
		queue.put("香蕉");
		queue.put("橘子");
		System.out.println(queue.take()); //取出并移除
		queue.put("西瓜"); //限制存3个,第4个阻塞了
		System.out.println(queue.take()); //取出并移除
		System.out.println(queue);
	}
}

2.4. 有界队列应用

//通过阻塞队列模拟生产者消费者模型
//案例:生产者和消费者个打印1~100,每次最多生产或消费4个
public class Test4 {
    
    
	public static void main(String[] args) {
    
    
		BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(4);
		
		//负责生产的线程
		new Thread(new Runnable() {
    
    
			
			@Override
			public void run() {
    
    
				for(int i=1;i<=100;i++) {
    
    
					try {
    
    
						queue.put(i);
						System.out.println("已经生产了第"+i+"件货");
					} catch (InterruptedException e) {
    
    
						e.printStackTrace();
					}
					
				}
			}
		}).start();
		
		
new Thread(new Runnable() {
    
    
			
			@Override
			public void run() {
    
    
				for(int i=1;i<=100;i++) {
    
    
					try {
    
    
						System.out.println("已经消费了第"+i+"件货");
						queue.take();
						
					} catch (InterruptedException e) {
    
    
						e.printStackTrace();
					}
					
				}
			}
		}).start();
	}
}


  1. IO流(重点)
    概念:程序与文件之间存储数据的通道

在这里插入图片描述

流的划分:

  1. 按方向划分: 输入流,输出流
    输入流:将文件中的数据读到程序中
    输出流:将程序的数据写到文件中

  2. 按单位划分: 字节流,字符流
    字节流:读写最小单位,按一个一个字节读写,效率低;读写所有文件(音频,视频,图片)
    字符流:按一个一个字符读写,效率高;只能读写文本文件

  3. 按功能划分:节点流,处理流
    节点流:基础流,没有经过处理的流
    处理流:经过处理包装后的流,功能更为强大

3.1 字节节点流

字节流的抽象父类: OutputStream,InputStream

子类:
字节流的节点流: FileOutputStream,FileInputStream

//------输出流-------
public class Test1 {
    
    
	public static void main(String[] args) throws IOException {
    
    
		OutputStream fos = new FileOutputStream("a.txt");  //文件路径参数
		//int类型参数,是存储码值
		//字符串转字节数组:
		fos.write("hello,world".getBytes()); 
		fos.close(); //打开文件,必须要关闭   io流的关闭  
		
	}
}

//------输入流-------
//字节节点流的读取:FileInputStream
//细节: 实例化输出流,会自动创建文件; 实例化输入流,则不会自动创建
//注意:在项目中使用IO流,往往捕获更多,咱们测试案例,后续用抛出更方便
public class Test2 {
    
    
	public static void main(String[] args) {
    
    
		FileInputStream fis = null;
		try {
    
    
			fis = new FileInputStream("a.txt");
			//System.out.println((char)fis.read());  //读取一个码值对应的字符
			byte[] b = new byte[1024];
			int len;  //读取字节数组,返回长度
			while((len=fis.read(b)) != -1) {
    
    
				//byte[]-->String
				//从下标0位置挨个转字符串,转len个
				System.out.println(new String(b,0,len)); 
			}

		} catch (IOException e) {
    
    
			e.printStackTrace();
		}finally {
    
    
			IOUtils.closeAll(fis);  //统一资源关闭---Closeable接口

		}
	}
}
//-------统一资源关闭--------
public class IOUtils {
    
    
	public static void  closeAll(Closeable... cs) {
    
    
		for(Closeable c : cs) {
    
    
			if(c!=null) {
    
    
				try {
    
    
					c.close();
				} catch (IOException e) {
    
    
					e.printStackTrace();
				}
			}
		}
	}
}


3.2 字节缓冲流

在这里插入图片描述

//------字节缓冲输出流-----
//字节缓冲流:BufferedOutputStream/BufferedInputStream
//带缓冲区的字节流--处理流(包装之后得到的流),减少与磁盘交互次数,提升了性能
//带两个参数的缓冲区对象,第二个参数是缓冲区大小,如果不指定默认为8192(1024*8,恒定值)
//越接近恒定值,缓冲区存储性能越好

public class Test1 {
    
    
	public static void main(String[] args) throws IOException {
    
    
		//BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
		
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"), 6);
		
		bos.write("hello,IO...".getBytes()); //缓冲区满了,也会写到磁盘文件
		//bos.flush();    //刷新缓冲区
		//bos.close();  //刷新缓冲区+close
	}
}


//-------字节缓冲输入流--------
//读取缓冲区内容
public class Test2 {
    
    
	public static void main(String[] args) throws IOException {
    
    
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
		byte[] b = new byte[104];
		int len;
		while((len=bis.read(b))!=-1) {
    
    
			System.out.println(new String(b, 0,len));
		}
		IOUtils.closeAll(bis);
		
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_45682261/article/details/125148297