A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小石姐姐 于 2018-11-30 15:06 编辑

day07 线程间通信 线程池 Lambda表达式

等待唤醒中的方法
java.lang.Object类:
        // 成员方法 (只能通过"锁对象"调用)
        void notify(): 随机唤醒在同一个锁对象上的某一个处于等待状态的线程
        void notifyAll(): 唤醒所有在同一个锁对象上处于等待状态的线程
        void wait(): 让当前线程处于无限等待状态, 同时释放锁

可以通过等待唤醒,实现线程的交替运行,
例如:
[AppleScript] 纯文本查看 复制代码
boolean lock=false;
A线程中
synchronized(lock)
{
if(lock){
lock.wait();//此处为方便阅读省略try catch,下同
}
...
Thread.sleep(2000);
lock=true;
lock.nofity();
}
b线程中
synchronized(lock)
{
if(!lock){
lock.wait();
}
...
lock=false;
lock.nofity();
}


线程池:
节省内存资源
java.util.concurrent.Executors类: 线程池工厂类, 用于创建和管理线程池
// 静态方法:
static ExecutorService newFixedThreadPool(int nThreads): 创建固定数量线程的线程池(常用)

java.util.concurrent.ExecutorService接口: 真正执行任务的线程池服务
// 成员方法:
Future submit(Runnable task): 提交一个Runnable任务
void shutdown(): 通知线程执行完任务后关闭. 如不调此方法, 则线程执行完任务后仍在运行以便重复使用


线程池的创建和使用步骤:
        1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService
        2. 创建一个任务类, 实现Runnable接口, 重写run()方法
        3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务
        4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)


lambda表达式
格式:(参数列表) -> {一些重写方法的代码}
应用条件:函数式接口:
        函数式接口: "有且仅有一个抽象方法的接口"
        但函数式接口对于 哪些方法算作抽象方法 有特殊规定:
                1. 有方法体的方法"不算作"抽象方法, 如默认方法, 静态方法, 私有方法
                2. 如果一个抽象方法 与 java.lang.Object类中的方法 定义相同的, 也"不算作"抽象方法
                        因为任何实现本接口的实现类, 都会直接或间接继承java.lang.Object类的public的方法, 所以在创建实现类时其实不用重写该抽象方法, 也就不算作抽象方法
  可以省略的部分:
        1. (参数列表): 参数"类型"可以省略 (a, b) -> {}
        2. (参数列表): 如果参数只有1个, 则"类型"和"小括号"都可以省略  a -> sout(a)
        3. {一些代码}: 如果只有一条代码, 则"大括号", "return", "分号"都可以"一起省略"


day08 File类 递归


file类:
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
        // 静态成员变量
    static String pathSeparator: 路径分隔符的字符串形式
    static char pathSeparatorChar: 路径分隔符的char形式
            Windows系统是 分号;  
        Linux系统是 冒号:
    static String separator: 文件名称分隔符的字符串形式
    static char separatorChar: 文件名称分隔符的char形式
            Window系统是 反斜杠\
        Linux系统是 正斜杠/
绝对路径:
        以盘符开始的路径
        如: "D:\\a\\hi.txt"
相对路径:
        不以盘符开始的简化路径. IDEA项目, 相对于项目的根目录
        如: "a\\1.mp3", "123.txt"
        "d:\\t"


File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
java.io.File类
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名  d:\a\b\c\aaa.txt
long length(): 获取File表示的"文件"大小的字节byte数 (不能获取目录的大小)
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件

// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
                false: 路径已经存在(无论文件还是目录)   
               抛IO异常: 写的路径不符合逻辑 (Y:\\a.txt\dsfsd)
boolean delete(): 删除由此File表示的文件或目录.
        删除目录时: 必须是空目录
boolean mkdir(): 创建File表示的目录  "d:\\a\\b\\c\\我的目录"
                false: 1. 路径已经存在(无论文件还是目录)   2. 写的路径不符合逻辑 (Y:\\a.txt\dsfsd)
boolean mkdirs(): 创建File表示的多级目录   "d:\\a\\b\\c\\我的目录"
                false: 1. 路径已经存在(无论文件还是目录)   2. 写的路径不符合逻辑 (Y:\\a.txt\ds)

// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组


递归:
Java中实现递归的方式:
        方法内部调用方法自己 (所以必须定义方法)

递归的分类:
        直接递归: 方法自己调用方法
        间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法

递归时的注意事项:
    1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出
    2. 递归次数不能太多, 否则会栈内存溢出
    3. 构造方法不能递归

递归的使用前提:
        调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归


递归求1-5的和:
[AppleScript] 纯文本查看 复制代码
public static void main(String[] args) {
        int sum = sum(5);
        System.out.println(sum);
}
public static int sum(int n) {
        if (n == 1) {
            return 1;
        }
      return n + sum(n-1);
}



递归打印多级目录:
[AppleScript] 纯文本查看 复制代码
File[] listFiles()
for(File file : arr) {
    if (是文件) {
        直接操作
    } else {
        是目录, 就递归调用方法
    }
}


FileFilter文件过滤器的原理和使用:
java.io.File类:  Filter过滤器
        File[] listFiles(FileFilter filter): 返回文件过滤器过滤后的File对象数组
        File[] listFiles(FilenameFilter filter): 返回文件过滤器过滤后的File对象数组

java.io.FileFilter接口: 用于File对象的过滤器
        boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入

java.io.FilenameFilter接口: 将File对象拆分为父路径和子路径来判断的过滤器
        boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入
                dir: 被找到的文件所在的目录 (父路径)
                name: 文件的名称          (子路径)


文件过滤器的Lambda优化例子:
//筛选出目录下.java文件和及目录,并存储为一个File数组
File[] childFiles = dir.listFiles((d, name) -> new File(d, name).isDirectory() || name.toLowerCase().endsWith(".java"));


day09 字节流 字符流 Properties


字节输出流: OutputStream和FileOutputStream
java.io.OutputStream抽象类: 字节输出流 (顶层类)
        // 成员方法
        void close() :释放资源
        void flush() :刷新缓冲区(对于字节流来说没有作用)
        // 写字节的成员方法
        abstract void write(int b): 一次写一个字节 (参数int便于传递byte的整数不用强转)
        void write(byte[] b): 一次写一个字节数组
        void write(byte[] b, int offset, int len): 一次写一个字节数组的一部分
        
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
        // 构造方法
        FileOutputStream(String name): 通过文件路径创建文件字节输出流
        FileOutputStream(File file): 通过File对象创建文件字节输出流
        构造方法的作用:
                1. 创建一个FileOutputStream对象
                2. 根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空数据")
                3. 将创建的FileOutputStream对象指向这个磁盘上的文件


文件存储原理和记事本打开文件的原理:
向文件中写入字节数据时, 十进制的数字会被转换为"二进制"的数字写入文件

文本编辑器打开文本文件时, 会先查询编码表, 将二进制数字转换为对应的字符进行显示
        0-127: 查询ASCII码表  -128~127
        其他: 查询系统默认码表
                        Windows简体中文系统的程序打开是按 GBK 码表
                        IDEA中使用的是 UTF-8 码表   

ASCII编码表: 1个byte就是一个字符
GBK编码表:   2个byte数字组成一个汉字
UTF-8编码表: 3个byte数字组成一个汉字 (utf-8其实是不定长的)


字节输出流: 续写, 换行:
java.io.FileOutputStream类: 文件字节输出流
        // 带有 续写 功能的构造方法, 不会清空文件
        FileOutputStream(String name, boolean append): 通过文件路径创建流, true可以续写
        FileOutputStream(File file, boolean append): 通过File对象创建流, true可以续写
        
换行符:
        Windows系统: "\r\n"
        Linux系统: "\n"
        MacOS系统: "\r"


字节输入流: InputStream和FileInputStream
java.io.InputStream抽象类: 字节输入流 (顶层类)
        // 常用成员方法
        void close(): 释放资源
        // 读数据的方法
        int read(): 一次读一个字节
                读到文件末尾返回-1 (返回int也是为了代码编写方便)
        int read(byte[] b): 一次读一个字节数组
                读到的字节存放在参数中的字节数组中, 返回int值是本次读到的字节的个数. 读到文件末尾返回-1

java.io.FileInputStream类: 文件字节输入流
        // 构造方法
        FileInputStream(String name): 使用文件路径创建文件字节输入流
        FileInputStream(File file): 使用File对象创建文件字节输入流
        构造方法的作用:
                1. 创建FileInputStream对象
                2. 将FileInputStream对象指向磁盘上的文件


字节流复制图片文件:
文件复制的步骤:
        1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
        2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
        3.使用字节输入流对象中的方法read读取文件
        4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
        5.释放资源


字节流读取中文问题:
编码不同不要使用字节流读取,会引起乱码,应使用day10中的转换流读取。

字符输入流: Reader和FileReader:
java.io.Reader抽象类: 字符输入流 (顶层)
        // 常用成员方法
        void close() :关闭此流并释放与此流相关联的任何系统资源
        // 读
        int read(): 一次读一个字符char, 返回读到的字符.
            读到文件末尾返回-1  (返回int为了代码编写方便)
        int read(char[] cbuf): 一次读取一个字符数组char[]
                返回读取的字符个数. 读到文件末尾返回-1

java.io.FileReader类: 文件字符输入流
        // 构造方法
        FileReader(File file): 根据File对象创建文件字符输入流
        FileReader(String fileName): 根据File对象创建文件字符输入流
        构造方法的作用:
                1. 创建FileReader对象
                2. 将FileReader对象指向磁盘上的文件


字符输出流: 续写, 换行:
FileWriter中带有续写功能的构造:
        FileWriter(File file, boolean append): 通过File对象创建流. 第二个参数为true可以续写
        FileWriter(String fileName, boolean append): 通过文件路径创建流. 第二个参数为true可以续写
        
换行:
        windows: "\r\n"  fw.write("\r\n");


字节流 和 字符流 如何选择:
        1. 如果不确定读写的是什么类型的数据, 用字节流最通用
        2. 如果确定读写的就是文本, 用字符流最方便


IO异常处理:
IO流操作中的异常处理:
IO流的标准格式:

     
[AppleScript] 纯文本查看 复制代码
   FileWriter fw = null;
    try {
        //IO流对象的创建, 操作等代码
        fw = new FileWriter("d:\\09_IOAndProperties\\g.txt", true);
        for (int i = 0; i <10 ; i++) {
            fw.write("HelloWorld"+i+"\r\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 释放资源
        if(fw != null){
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }




JDK7和JDK9中IO异常处理的不同方式:

JDK 7 增加的 "try-with-resource"
        省略了 finally, 可自动释放资源

// 格式
        try (创建流对象语句,如果多个,使用';'隔开) {
                // 读写数据   
        } catch (IOException e) {
                e.printStackTrace();   
        }


JDK 9 对于"try-with-resource"的改进:
        流对象的声明和创建可以放在括号外面
        流对象要求是有效final的.(即不要修改流对象的值)


Properties集合:
Properties存储数据和遍历:
Properties双列集合:
        键和值都是 String 类型

java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
        // 构造方法
        Properties(): 创建一个Properties集合
        // 可以使用Map接口中的方法
        // 特有成员方法
        Object setProperty(String key, String value): 保存/替换键值对
        String getProperty(String key): 通过键获取值. 键不存在返回null
        Set<String> stringPropertyNames(): 返回键的集合
        void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
        void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文),并写入注释
        void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能中文)
        void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以中文)


Properties: store()存储数据到文件:
Properties将数据写入到文件的方法:
        void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
        void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文), 并写入注释
        
使用步骤:
        1.创建Properties集合对象,添加数据
        2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
        3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        4.释放资源




Properties: load()从文件加载数据到集合

Properties将数据从文件加载到集合中的方法:
        void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
        void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)

使用步骤:
        1.创建Properties集合对象
        2.使用Properties集合对象中的方法load读取保存键值对的文件
        3.遍历Properties集合



day10 缓冲流 转换流 序列化流 打印流


缓冲字节输出流: BufferedOutputStream:
字节缓冲流
        |_ BufferedInputStream     # 缓冲字节输入流
        |_ BufferedOutputStream    # 缓冲字节输出流

字符缓冲流
        |_ BufferedReader          # 缓冲字符输入流
        |_ BufferedWriter          # 缓冲字符输出流
        
java.io.BufferedOutputStream类: 缓冲字节输出流
        // 构造方法
        BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
        BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
        
BufferedOutputStream使用步骤:
        1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地
        2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象
        3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
        4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
        5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)

        FileOutputStream fos = new FileOutputStream("文件路径");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bos.write("你好".getBytes());
        // bos.flush();  // 可以省略
        bos.close();


缓冲字节输入流: BufferedInputStream
java.io.BufferedInputStream类: 缓冲字节输入流
        // 构造方法
        BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
        BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小
        
使用步骤:
        1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
        2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象
        3.使用BufferedInputStream对象中的方法 read(), 读取文件
        4.释放资源 close()

        FileInputStream fis = new FileInputStream("文件路径");
        BufferedInputStream bis = new BufferedInputStream(fis);
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
        System.out.println(new String(bytes, 0, len));
    }
        bis.close();


缓冲流 + 一次读写一个字节数组 效率最高

缓冲字符输出流: BufferedWriter:

java.io.BufferedWriter类:
        // 构造方法
        BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
        BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
        // 特有方法
        void newLine(): 写入一个换行符, 换行符自动根据当前系统确定


缓冲字符输入流: BufferedReader:

java.io.BufferedReader类: 缓冲字符输入流
        // 构造方法
        BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流
        BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
        // 特有方法
        String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null


转换流:
OutputStreamWriter类介绍及使用:
java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
        // 构造方法
        OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
        OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流

        
// 使用默认UTF-8
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));
o.write("dsfdsfdsaf")

// 使用指定的GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
                osw.write("你") -> 查"GBK"码表 -> -1,-2 -> FileOutputStream -> a.txt文件
         写数据: 字符流 --------------------------> 字节流


InputStreamReader类介绍及使用:
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
        // 构造方法
        InputStreamReader(InputStream in): 使用默认编码表创建转换流
        InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
        
// 使用默认UTF-8
InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"));

// 使用指定的GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
     '你' <- 查"GBK"码表 <- isr.read() <- -1,-2 <- FileInputStream <- a.txt文件
                         读数据: 字符流 <---------- 字节流        


序列化流(对象流):
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中
        对象 -> 字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象
        字节 -> 对象

通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态

OutputStream
        |_ ObjectOutputStream类: 对象字节输出流
InputStream
        |_ ObjectInputStream类: 对象字节输入流


对象序列化流: ObjectOutputStream:
java.io.ObjectOutputStream类: 对象字节输出流
        // 构造方法
        ObjectOutputStream(OutputStream out)
        // 特有成员方法
        void writeObject(Object obj): 将对象写出
        
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18);
oos.writeObject(s);
// 释放资源
oos.close();

注意:
        被读写的对象的类必须实现"java.io.Serializable"接口, 否则会抛出"NotSerializableException"


对象反序列化流: ObjectInputStream:
java.io.ObjectInputStream类: 对象字节输入流
        // 构造方法
        ObjectInputStream(InputStream in)
        // 特有成员方法
        Object readObject(): 读取对象
        
// 创建对象输入流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));
// 读对象
Object o = oos.readObject();
Student s = (Student)o;
System.out.println(s);
// 释放资源
oos.close();


transient瞬态关键字: 避免属性序列化:
static 修饰的成员变量属于类不属于对象, 所以不能序列化
transient 修饰的成员变量, 不能被序列化

transient 应用场景:
        如果对象的某个属性不希望被序列化, 可以使用 transient 修饰, 这样就不会被对象流写到文件中


InvalidClassException异常: 原因和解决方案:
serialVersionUID序列号的作用:
        序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
        该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化
        当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException

为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的


打印流:
打印流PrintStream: 概述和使用:
PrintStream特点:
        1. 只有输出流, 没有输入流
        2. PrintStream不会抛出IOException
        3. 有特殊方法 print(), println(), 可以输出任意类型的值, 原样输出
java.io.PrintStream类: 字节打印流
        // 构造方法
        PrintStream(File file): 创建字节打印流, 输出到一个文件
        PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
        PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
注意事项:
        如果用 write(97) 方法, 会查编码表   97 -> a
        如果用 print(97), println(97), 则原样输出  97 int -> '9''7' -> byte -> 文件 97
        System.out.println();
        PrintStream out;
java.lang.System类:
        // 静态方法
        static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流


IO框架体系结构:
// 体系结构:
字节流
        |_ InputStream                 # 字节输入流
        |        |_ FileInputStream         # 专门操作文件的字节输入流
        |        |_ BufferedInputStream     # 带有缓冲区的字节输入流, 效率高
        |        |_ ObjectInputStream       # 对象输入流
        |
        |_ OutputStream                # 字节输出流
                |_ FileOutputStream        # 专门操作文件的字节输出流
                |_ BufferedOutputStream    # 带有缓冲区的字节输出流, 效率高
                |_ ObjectOutputStream      # 对象输出流
                |_ PrintStream             # 字节打印流
字符流
        |_ Reader                      # 字符输入流
        |        |_ BufferedReader          # 带有缓冲区的字符输入流, 效率高
        |        |_ InputStreamReader       # 将字节流转换为字符流输入的转换输入流
        |                |_ FileReader          # 专门操作文件的字符输入流        
        |
        |_ Writer                      # 字符输出流
                |_ BufferedWriter          # 带有缓冲区的字符输出流, 效率高
                |_ OutputStreamWriter      # 将字符流转换为字节流输出的转换输出流
                |     |_ FileWriter         # 专门操作文件的字符输出流


附打砖块java小程序(有些功能正在开发中。。):
[Java] 纯文本查看 复制代码
package olddriver;[/size][/color][/size][/color]
import javax.swing.*;
import java.awt.*;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.concurrent.Executors.newFixedThreadPool;


public class OnScreen extends JFrame implements KeyListener{
    public static final ReentrantLock lock=new ReentrantLock();
    private static final int FRONTLINE =34, LEFTLINE =32;
    private static int playerpoint= LEFTLINE /2-3;
    private static final int HIGH = FRONTLINE -2;
    private static ArrayList<Boolean> monster_row1  = new ArrayList<>();
    private static ArrayList<Boolean> monster_row2  = new ArrayList<>();
    private static ArrayList<Boolean> monster_row3  = new ArrayList<>();
    private static ArrayList<Boolean> monster_row4  = new ArrayList<>();
    private static ArrayList<Boolean> monster_row5  = new ArrayList<>();
    private static ArrayList<Boolean> monster_row6  = new ArrayList<>();
    private static ArrayList<Boolean> monster_list  = new ArrayList<>();
    private static ArrayList<ArrayList<Boolean>> monster_row =new ArrayList<>();
    private static int ball_row = LEFTLINE /2;
    private static int ball_list = HIGH -1;
    private static boolean gamestart=false;
    private static int gamespeed=100;
    private static boolean gameover=true;
    private static boolean hardselect=false;
    private static final String info="哲学版打方块5.0版本 \n 请选择游戏难度 \n 数字键:0-6 \n 其它键为默认难度 \n 0最快 6最慢 \n 左右键或者AD键控制方向";
    private static ExecutorService gameline=newFixedThreadPool(2);
    private Center center=new Center();
    private FlushWindow flushWindow=new FlushWindow();
    private static JMenuBar jMenuBar=new JMenuBar();
    private static JMenu jMenu1=new JMenu("文件");
    private static JMenuItem jMenuItem1=new JMenuItem("打开历史记录");
    private static File savefile=new File("abc.save");
    private static FileInputStream load;
    JPanel jp1;
    static JTextPane jt1;

    public OnScreen(){
        jp1=new JPanel();
        jt1=new JTextPane();
        jp1.add(jt1);
        jt1.setPreferredSize(new Dimension(450,590));
        jt1.setEditable(false);
        jt1.setFont(new Font("黑体", Font.BOLD,30));
        jt1.addKeyListener(this);
        this.add(jp1, BorderLayout.CENTER);
        this.setSize(500,690);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocation(800,360);
        this.setResizable(false);
        this.setVisible(true);
        this.setTitle("哲学版打方块5.0!!!");
        this.setJMenuBar(jMenuBar);
        jMenuBar.add(jMenu1);
        jMenu1.add(jMenuItem1);
        if (!savefile.exists()) {
            try {
                savefile.createNewFile();
            } catch (IOException e) {

            }
        } else{
            try {
                load=new FileInputStream(savefile);
            } catch (FileNotFoundException e) {

            }
        }


    }
    public static void main(String[] args) {
        gameInit();
        OnScreen onScreen=new OnScreen();
        jt1.setText(info);
//        playerpoint=LEFTLINE-6;

        /*//左右移动小测试
        boolean left=false;
        boolean right=false;
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (playerpoint<LEFTLINE-6 && !right){
                playerpoint++;
            } else if (playerpoint==LEFTLINE-6){
                playerpoint--;
                right=true;
            } else if(playerpoint==1){
                playerpoint++;
                right=false;
            } else if (right && playerpoint>1){
                playerpoint--;
            }
            onScreen.jt1.setText(onScreen.flushScreen(playerpoint));
        }*/
        //

        //刷新画面

//        onScreen.center();
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (!gamestart && !hardselect) {
            gameHard((char)e.getKeyCode());
            hardselect=true;
        }
        if (!gamestart && hardselect){
            jt1.setFont(new Font("黑体", Font.BOLD,12));
            gamestart=true;
            gameover=true;
            gameline.submit(center);
            gameline.submit(flushWindow);
            playerpoint++;
        }
        if ((e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_A) && playerpoint>1 && gameover){
            playerpoint--;
        }
        if((e.getKeyCode()==KeyEvent.VK_RIGHT || e.getKeyCode()==KeyEvent.VK_D) && playerpoint< LEFTLINE -6 && gameover){
            playerpoint++;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if ((e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_A) && playerpoint>1 && gameover){
            playerpoint--;
        } else if((e.getKeyCode()==KeyEvent.VK_RIGHT || e.getKeyCode()==KeyEvent.VK_D) && playerpoint< LEFTLINE -6 && gameover){
            playerpoint++;
        }
    }

    public static String flushScreen(int playerpoint){
        String temp="";
        for (int i = 0; i <= FRONTLINE; i++) {
            for (int i1 = 0; i1 <= LEFTLINE; i1++) {
                if(i == 0 || i == FRONTLINE) {
                    temp=(temp+"□");
                } else if(i1 == 0 || i1 == LEFTLINE) {
                    temp=(temp+"□");
                } else if(i == HIGH && i1 == playerpoint) {
                    temp=(temp+"======");
                    i1 += 5;
                } else if(monster_list.get(i) && monster_row.get(i>0&&i<6?i-1:5).get(i1)) {
                    temp=(temp+"♂");
                } else if(ball_list==i && ball_row==i1){
                    temp=(temp+"Ο");
                } else {
                    temp=(temp+" ");
                }
            }
            temp=(temp+"\n");
        }
        return temp;
    }

    public static class Center implements Runnable{
            @Override
            public void run() {
                boolean left_wall=true;
                boolean right_wall=false;
                boolean front_wall=false;
                boolean kick=true;
                boolean dead=false;
                boolean kill_monster=false;
                synchronized (lock){
                    ArrayList<Integer> temp=new ArrayList<>();
                    while (gameover) {
                        temp.clear();
                        for (int i = 0; i < 6; i++) {
                            temp.add(playerpoint+i);
                        }
                        int point=temp.indexOf(ball_row);
                        try {
                            Thread.sleep(gamespeed);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(ball_list==FRONTLINE-1){
                            dead=true;
                        }
                        if(ball_row==LEFTLINE-1){
                            right_wall=true;
                            left_wall=false;
                        }
                        if(ball_list==1){
                            front_wall=true;
                            kick=false;
                        }
                        if(ball_row==1){
                            right_wall=false;
                            left_wall=true;
                        }
                        if(ball_list<7){
                            if(monster_row.get(ball_list-1).get(ball_row-1)){
                                monster_row.get(ball_list-1).set(ball_row-1,false);
                                if(monster_row.get(ball_list).get(ball_row-1)){
                                    monster_row.get(ball_list).set(ball_row-1,false);
                                }
                                kill_monster=true;
                                kick=false;
                            }
                        }
                        if(ball_list==HIGH-1 && (point != -1)){
                            kick=true;
                            front_wall=false;
                            kill_monster=false;
                            if(point==0) {
                                if(left_wall) {
                                    right_wall = true;
                                    left_wall = false;
                                }
                            }
                            if(point==5) {
                                if(right_wall) {
                                    right_wall = false;
                                    left_wall = true;
                                }
                            }


                        }
                        if(dead){
                            gameover=false;
                            jt1.setText("你死啦!! \n 莫慌!5秒后游戏重新开始。。");
                            jt1.setFont(new Font("黑体",Font.BOLD,25));
                            try {
                                Thread.sleep(5000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            gameOver();
                            break;
                        }
                        if(left_wall){
                            ball_row++;
                        }
                        if(right_wall){
                            ball_row--;
                        }
                        if(front_wall){
                            ball_list++;
                        }
                        if(kick){
                            ball_list--;
                        }
                        if(kill_monster){
                            ball_list++;
                        }
                        jt1.setText(flushScreen(playerpoint));
                    }
                }

            }
    }

    private static void init(boolean b){
            monster_row1.add(b);
            monster_row2.add(b);
            monster_row3.add(b);
            monster_row4.add(b);
            monster_row5.add(b);
    }

    public static void gameHard(char hard){
        switch (hard){
            case '0':
                gamespeed=33;
                break;
            case '1':
                gamespeed=66;
                break;
            case '2':
                gamespeed=100;
                break;
            case '3':
                gamespeed=200;
                break;
            case '4':
                gamespeed=300;
                break;
            case '5':
                gamespeed=400;
                break;
            case '6':
                gamespeed=500;
                break;
            case 96:
                gamespeed=33;
                break;
            case 97:
                gamespeed=66;
                break;
            case 98:
                gamespeed=100;
                break;
            case 99:
                gamespeed=200;
                break;
            case 100:
                gamespeed=300;
                break;
            case 101:
                gamespeed=400;
                break;
            case 102:
                gamespeed=500;
                break;
            default:
                gamespeed=200;
                break;
        }
    }

    public static class FlushWindow implements Runnable{
        @Override
        public void run() {
            synchronized (lock) {
                while (gameover) {
                    jt1.setText(flushScreen(playerpoint));
                    try {
                        Thread.sleep(33);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void gameOver() {
        gameInit();
        jt1.setText(info);
    }

    public static void gameInit(){
        playerpoint= LEFTLINE /2-3;
        monster_row1  = new ArrayList<>();
        monster_row2  = new ArrayList<>();
        monster_row3  = new ArrayList<>();
        monster_row4  = new ArrayList<>();
        monster_row5  = new ArrayList<>();
        monster_row6  = new ArrayList<>();
        monster_list  = new ArrayList<>();
        monster_row =new ArrayList<>();
        ball_row = LEFTLINE /2;
        ball_list = HIGH -1;
        gamespeed=100;

        init(false);
        for (int i=1;i<LEFTLINE;i++){
            init(true);
        }
        init(false);
        for (int i=0;i<=LEFTLINE;i++) {
            monster_row6.add(false);
        }
        monster_list.add(false);

        for (int i = 1; i < 6; i++) {
            monster_list.add(true);
        }
        for (int i = 6; i < FRONTLINE; i++) {
            monster_list.add(false);
        }
        monster_row.add(monster_row1);
        monster_row.add(monster_row2);
        monster_row.add(monster_row3);
        monster_row.add(monster_row4);
        monster_row.add(monster_row5);
        monster_row.add(monster_row6);

        gamestart=false;
        gameover=false;
        hardselect=false;
    }

}



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马