title: Java学习之路-《周记》
文章目录
一、整体知识点
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(); //关闭流
-
- 思维导图:
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一段时间)
二、经典代码
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();
}
}