Java学习之路-《周记》--菜鸟小回


title: Java学习之路-《周记》

文章目录

    • title: Java学习之路-《周记》
  • 一、整体知识点
    • 1.异常
    • 2.File类
    • 3.多线程
  • 二、经典代码
    • 1.自写工具类CopyFileTool和CopyDirectoryTool
    • 2.多线程问题-多窗口卖票
    • 3.多线程问题-超市进货,出货

一、整体知识点


1.异常

  • Exception:异常,代码在运行期间出现的例外

    • 编译期异常:必须处理的异常,不处理无法通过编译。不能避免
      1、抛异常 throws,在方法的参数列表和方法体之间抛出异常
      2、try-catch,捕捉异常
      try{//try代码块
      可能出现异常的代码
      }catch(异常的类型 异常名){
      处理异常
      }finally{
      必须执行的代码块
      }
      除了RuntimeException的其他exception

    运行时异常:不必须处理的异常,可以避免。父类RuntimeException

  • 自定义异常
    1、如果定义编译期异常,继承Exception类

        public class AgeGreaterThanTwoHundredException extends Exception{
        //Exception 编译期异常
    	private static final long serialVersionUID = 1L;
    	
    	public AgeGreaterThanTwoHundredException(){
    		super("You can't be older than 200!");
    	}
    	public AgeGreaterThanTwoHundredException(String message){
    		super(message);
    	}
        }
    

    2、如果定义运行时异常,继承RuntimeException

    public class AgeLessThanZeroException extends RuntimeException{	//运行时异常
    
    	private static final long serialVersionUID = 1L;
    
    	public AgeLessThanZeroException() {
    		super("Age can't be less than 0!");
    	}
    
    	public AgeLessThanZeroException(String message){
    		super(message);
    	    }
        }
        ```
    
  • 使用自定义异常:

    public void setAge(int age) throws AgeGreaterThanTwoHundredException {	//编译期异常需要声明异常类型
    		if(age<0){
    			throw new AgeLessThanZeroException();
    		}else{
    			if(age>200){
    				throw new AgeGreaterThanTwoHundredException();		//抛出异常
    			}else
    				{this.age=age;}
    		}
    	}
    
  • Error:错误


2.File类

  • java.io
    • File类没有无参构造方法,每一个file对象都必须标识一个文件或者文件夹
    • 创建(注意路径\\ )://使用文件的路径,构建出文件对象 File file1=new File("E:\\Test\\day02");
      //使用父文件夹对象类创建文件对象 File parent=new File("E:\\Test"); File file2=new File(parent,"day02");
  • io
    • i:inputstream 输入流,读
    • o:outputstream 输出流,写
    • 传输的单位不同分为:字节流、字符流
    • 传输的方向不同:输入流、输出流
  • InputStream
    • 实例化需要通过文件类型;
      InputStream is=new FileInputStream(file1);
      	
      	//定义一个缓冲区
      	byte[] b=new byte[1024];		//1kb
      	//获取字符流长度,当长度等于-1时,说明文件读完
      	int len=is.read(b);
      	
      	while(len!=-1){		//文件未读完
      		String str=new String(b, 0, len);		//将读取到缓冲区赋值给字符串
      		System.out.println(str);
      		len=is.read(b);			//继续读取下一个字符流
      	}
      	is.close();//注意关闭
      
  • outputstream
    •   OutputStream out=new FileOutputStream(file1,true);
        		String str="还是那么爱你,就像风走了几万里!";
        		out.write(str.getBytes());		//写入文件
        		out.flush();				//刷新流
        		out.close();				//关闭流
      
  • 思维导图:
    Java学习之路-《周记》--菜鸟小回_第1张图片

3.多线程

  • 进程:一个程序的执行过程

  • 线程:在一个进程中包含多个独立执行的单元,

  • Thread类
    start方法开启线程
    sleep方法,休眠,线程会进入阻塞状态

  • 多线程的实现方式:
    1、继承Thread类,重写run方法
    2、实现Runnable接口,重写run方法(推荐使用)
    Thread t1=new Thread(new 实现类名);

  • synchronized同步
    1、同步代码块
    synchronized (o) {同步块}
    2、方法同步
    [修饰符] synchronized 返回值类型 方法名([参数列表]){
    方法体;
    }

    • 同步的代码块越小,不可能分割的能力越强。
    • 被锁住的部分同时只允许一个线程通过
  • 死锁:占用、等待、对方不可剥夺
    1、互斥
    2、不可剥夺
    3、等待
    4、保持
    使用wait和notify来控制线程的执行顺序,使用在同步块中

  • 经典死锁

synchronized (obj1) {
			
			System.out.println("我拿到遥控器");
			synchronized (obj2) {
				System.out.println("我拿到电池");
				obj2.notify();
			}
			System.out.println("我的电池使用完毕");
			
		}
		System.out.println("我的遥控器使用完毕");
synchronized (obj2) {
			try {
				obj2.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("你拿到电池");
			synchronized (obj1) {
				System.out.println("你拿到遥控器");
			}
			System.out.println("你遥控器使用完毕");
			
		}
		System.out.println("你电池使用完毕");
  • 分析:当 1 拿到遥控器时,2可能正好拿到电池,此时同步块不允许其他线程进入,自己本身也无法倒退。1需要遥控,2需要电池。程序进入死锁。
    利用wait 2,进入同步锁obj2后,等待,不会向下进行,直到 1的 notify被运行,wait结束,继续向下执行。 (利用wait等待时注意让其先执行,即所等代码块先sleep一段时间)

Java学习之路-《周记》--菜鸟小回_第2张图片


二、经典代码


1.自写工具类CopyFileTool和CopyDirectoryTool

复制文件方法:

package com.zhiyou.work;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;

public class CopyFileTool {

	public static void copyFile(String fileFrom,String fileTo) throws IOException{

		//实例化目标文件
		File fi=new File(fileFrom);
		//实例化目的文件父文件
		File fi2=new File(fileTo);

		//如果目的文件父文件夹不存在
		if(!fi2.exists()){
			fi2.mkdirs();	//创建目的文件夹
		}
		//创建目的文件
		File fi3=new File(fileTo,fi.getName());
		//如果目的文件不存在
		if(!fi3.exists()){
			fi3.createNewFile();		//创建文件
		}else
		{
			throw new CopyException("目的文件已存在,请检查!");		//抛出异常
		}

		InputStream is = null;
		OutputStream os=null;
		try{
			//文件输入输出流实例化
			long process = 0;
			is=new FileInputStream(fi);
			os=new FileOutputStream(fi3);
			//数据转移
			long length =fi.length();//文件的字节长度
			byte[] by=new byte[1048576];//1M
			int len;
			while((len=is.read(by))!=-1){
				os.write(by,0,len);
				process+=len;
				DecimalFormat df = new DecimalFormat("#0.00%");
				System.out.println(df.format((double)process/length));
			}
			//关闭输出流
			os.flush();
			System.out.println("复制完成!");

		}catch(IOException e){
			e.printStackTrace();
		}finally{
			try{
				if(is!=null){
					is.close();
				}
				if(os!=null){
					os.close();
				}
			}catch(IOException e){
				e.printStackTrace();
			}

		}


	}
}

复制文件夹:

package com.zhiyou.work2;

import java.io.File;
import java.io.IOException;

import com.zhiyou.work.CopyException;
import com.zhiyou.work.CopyFileTool;

public class CopyDirectoryTool {

	/**
	 * 复制的方法
	 * @param fileFrom 需要复制的文件对象
	 * @param fileTo 复制到的文件夹中
	 * 如果fileFrom或者fileTo为""或者null,直接复制失败
	 * 如果需要复制的文件夹已经存在,复制失败
	 */
	public static void copy(String fileFrom,String fileTo) throws IOException{
		if(fileFrom==null||fileTo==null){
			return;
		}
		if(fileFrom.equals("")||fileTo.equals("")){
			return;
		}
		
		File fi=new File(fileFrom);	//目标文件名
		File fi2=new File(fileTo);
		if(fi.isFile()){	//是文件,直接使用文件复制方法
			CopyFileTool.copyFile(fileFrom, fileTo);
		}else 
		{
			
			File fi3=new File(fi2,fi.getName());
			String[] str=fi.list();
			
			//不存在文件夹则先复制文件夹
			if(fi3.exists()){
				throw new CopyException("目的文件已存在,请检查!");		//抛出异常
			}else{
				fi3.mkdir();
			}
			
			for (String name : str) {
				//首次"E:\\work", "E:\\ab"
				//下次"E:\\work+name","E:\\ab+work(fi.getname())"
					copy(fi.getPath()+"\\"+name,fi2.getPath()+"\\"+fi.getName());
			}

		}


	}
}

自定义文件重复异常类:

package com.zhiyou.work;


public class CopyException extends RuntimeException{

	private static final long serialVersionUID = 1L;

	public  CopyException() {
		super("文件复制失败,检查目标文件路径是否出错!!!");
	}
	
	public  CopyException(String message) {
		super(message);
	}
	
}


2.多线程问题-多窗口卖票

package com.zhiyou.work1;

public class Ticket implements Runnable{

	//类变量所有成员共享
	static int ticket=200;
	String name;
	public Ticket(){

	}
	public Ticket(String name) {
		this.name=name;
	}
	Object obj="z";
	@Override
	public void run() {

		while(ticket>0){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			synchronized (obj) {

				if(ticket==0){
					break;
				}
				System.out.println(name+"卖出第"+ticket+"张票");
				ticket--;
				if(ticket==0){
					System.out.println("对不起,票已卖完!");
				}
			}	
		}
	}
}

package com.zhiyou.work1;

public class Test {
	public static void main(String[] args) {
		Ticket ti1=new Ticket("第一窗口");
		Ticket ti2=new Ticket("第二窗口");
		Ticket ti3=new Ticket("第三窗口");
		Ticket ti4=new Ticket("第四窗口");
		Ticket ti5=new Ticket("第五窗口");
		
		Thread t1=new Thread(ti1);
		Thread t2=new Thread(ti2);
		Thread t3=new Thread(ti3);
		Thread t4=new Thread(ti4);
		Thread t5=new Thread(ti5);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		
	}
}


3.多线程问题-超市进货,出货

package com.zhiyou.work2;

public class Product {

	int xid;

	public Product() {
	}
	public Product(int xid) {
		super();
		this.xid = xid;
	}
	public int getXid() {
		return xid;
	}

	public void setXid(int xid) {
		this.xid = xid;
	}
}


package com.zhiyou.work2;

public class Shop {

	Product[] products=new Product[20];

	static int index=0;
	
	synchronized Product sell(){
		
		if(index==0){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		index--;
		Product p=products[index];
		System.out.println("顾客买走了"+(index+1)+"上的商品");
		this.notifyAll();
		return p;
	}
	
	synchronized void jinhuo(Product p){
		if(index==20){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		products[index]=p;
		index++;
		System.out.println("供货商在"+index+"位置上放上商品"+p.getXid());
		this.notifyAll();
	}

}

package com.zhiyou.work2;

public class ProductFrom implements Runnable{

	Shop shop;
	public ProductFrom(Shop shop) {
		super();
		this.shop = shop;
	}
	@Override
	public void run() {
		for(int i=1;i<=50;i++){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Product p=new Product(i);
			shop.jinhuo(p);
		}
	}

}

package com.zhiyou.work2;

public class Consumer implements Runnable{

	Shop shop;
	@Override
	public void run() {
		for(int i=1;i<=50;i++){
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Product p=shop.sell();
		}
	}
	public Consumer(Shop shop) {
		super();
		this.shop = shop;
	}
}

package com.zhiyou.work2;

public class Test {
	public static void main(String[] args) {
		Shop shop=new Shop();
		Thread t1=new Thread(new ProductFrom(shop));
		Thread t2=new Thread(new Consumer(shop));
		t1.start();
		t2.start();
	}
}

你可能感兴趣的:(基础)