javaIO流学习笔记02

x33g5p2x  于2021-11-26 转载在 Java  
字(6.8k)|赞(0)|评价(0)|浏览(337)

首先说一下昨天的小问题:

那就是为什么总是第一个人再抢票?为什么总是打印输出了第一个.start的线程,但是明明线程是正常运转的:我们昨天完善的最好的一次就是使用 List<Integer> list = new ArrayList<>();,用这个数组来存放获取到的票就可以很好的显示结果:

而且从下面这个方法可以将 synchronized(ob)改成 synchronized(this)即使前面输出错误最后的list依然可以存放正确,说明问题的原因并不是在 synchronized()上面:

package 任务十__多线程.售票;

import java.util.ArrayList;
import java.util.List;

public class TestDemo {

    //定义售票线程类(也就是窗口)
    public static class Station extends Thread{
        //构造方法给线程名字赋值
        public Station(String name) {
            super(name);
        }
        //票数要静态定义
        static int tick=50;
        //静态钥匙
        static Object ob ="key"; //值是任意的
        //重写run方法,实现售票操作
        @Override
        public void run() {
            List<Integer>  list = new ArrayList<>();
            while (tick>0) {
                synchronized(ob) { //必须使用一个同步锁,进去的人会把钥匙拿在手上,出来后才能交出钥匙
                    if (tick>0) {
                        System.out.printf("%s卖出了第%d张票 \n",getName(),tick);
                        list.add(tick);
                        tick--;
                    }else {
                        System.out.printf("%s:票已售空 \n",getName());

                    }
                }
                try {
                    sleep((int)(Math.random()*3000)+1); //随机休息1-3000ms
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.printf("%s 销售情况: %s \n",getName(),list.toString());
        }
    }

    public static void main(String[] args) {
        //实例化站台对象,并为每一个站台取名字(8个线程窗口一起卖5张票)
        for (int i=1; i<=8; i++) {
            String sName="窗口" + String.valueOf(i);
            Station  Station = new Station(sName);
            Station.start();
        }

    }

}

然后我们想一下为什么,通过上面这个成功例子映射一下,这个例子比其他代码多了一个什么步骤?那就是存放票,可以看的更清楚,所以我们尝试再锁 synchronized()之前加入一行代码: System.out.println(getName()+"正在卖票");

package 任务十__多线程.售票;

/** * @author ${范涛之} * @Description * @create 2021-11-24 23:43 */
class SaleThread extends Thread {

    /** * 使用静态成员变量作为100张票的保存变量,是一个共享资源。 */
    private static int tickets = 20;

    public  SaleThread(String name){
        super(name);
    }

    @Override
    public void run() {
        // 完成售票过程
        while (true) {

            System.out.println(getName()+"正在卖票");
            synchronized (this) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "售出了" + tickets + "张票");
                    tickets--;
                } else {
                    System.out.println(Thread.currentThread().getName() + "售罄!!!");
                    break;
                }
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {

        new SaleThread("范涛之").start();
        new SaleThread("张荣康").start();
        new SaleThread("秦舒下").start();

    }
}

运行结果:

为什么要加这句话才可以输出成功?答案:

因为线程即使执行完System.out.println(getName() + “抢到了第” + ticket + “火车票”);但是还没来得及打印,就被别的线程抢走了,等别的线程打印了,他可能抢到执行时间,才会打印,所以,在上面加一行System.out.println(getName() + “正在抢票…”);系统打印就能正确显示。
程序并没有错误,只是System.out.println跟不上线程的速度。

也就是说为什么总是在打印第一个人,因为的就是线程来不及去打印其他人!

分割线·····················································································

JavaIO流:

怎样递归一个盘下面的所有目录:

思路:1:首先通过过file.listFiles()方法获取目录下的所有文件(包含子目录下的所有文件),得到files[]数组,后续的增强for循环中就是通过比较数组中的值是文件还是目录

2:然后遍历得到的所有文件

3:通过isFile(文件)和isDirectory(文件夹)方法来判断读取的是文件还是文件夹,如果得到的是文件夹,就递归调用test()方法,如果得到的是文件,就将其加入fileList中,

4:最后测试的时候遍历fileList下的所有文件,来验证读取数据的准确性。

代码实现:

1:首先新建一个文件类型的集合:

List<File> fileList = new ArrayList<File>();

然后引入File,并且创建file.listFiles():

File file = new File(fileDir);
            File[] files =  file.listFiles();

然后先判断files是否为空,要是空直接返回:

if (files==null){
                return;
            }

接下来判断是文件还是目录:目录则递归,文件则添加:

for (File f :files){
                if (f.isFile()){
                    fileList.add(f);

                }else if (f.isDirectory()){
                    System.out.println(f.getAbsolutePath());
                    test(f.getAbsolutePath());    //递归调用
                }
            }

遍历集合打印:

for (File f1 :fileList){
                System.out.println(f1.getName());
            }

主方法传入值:

public static void main(String[] args) {
        test("C:/");
    }

全部代码:

package 任务11IO流;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/** * @author ${范涛之} * @Description * @create 2021-11-25 12:31 */
public class Test5 {

    private  static  void  test(String fileDir){

            List<File> fileList = new ArrayList<File>();
            File file = new File(fileDir);
            File[] files =  file.listFiles();
            if (files==null){
                return;
            }
            for (File f :files){
                if (f.isFile()){
                    fileList.add(f);

                }else if (f.isDirectory()){
                    System.out.println(f.getAbsolutePath());
                    test(f.getAbsolutePath());    //递归调用
                }
            }
            for (File f1 :fileList){
                System.out.println(f1.getName());
            }
    }

    public static void main(String[] args) {
        test("C:/");
    }

}

运行截图:

怎样使用java复制文件:一共有四种方法:

1. 使用FileStreams复制:是最经典的方式将一个文件的内容复制到另一个文件中。 使用FileInputStream读取文件A的字节,使用FileOutputStream写入到文件B。 这是第一个方法的代码:(字节流)

package 任务11IO流;

import java.io.*;

public class Test6{

    private  static  void  copyFileUsingFileStreams(String source, String dest) throws IOException {
        InputStream input = null;
        OutputStream output = null;

        try {
            input = new FileInputStream(source);
            output = new FileOutputStream(dest);
            byte[] buf = new  byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buf))>0){
                output.write(buf,0,bytesRead);

            }

        }finally {
            input.close();
            output.close();
        }

    }

    public static void main(String[] args) throws IOException {
        copyFileUsingFileStreams("H:\\bilbil\\07.mp4","F:\\shipin\\007.mp4");
    }
}

运行结果:

首先讲解一下一些参数:

  • source和dest分别是自定义的源文件位置和待复制的位置

  • output.write(buf,0,bytesRead);:其实这里也就是FileOutputStream.write:后面的三个参数依次是:byte[] b, int off, int len,也就是将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。偏移量也就是相对位置的意思。

  • input.read同上等于FileInputStream.read:read(byte[] b, int off, int len) 的意思就是从该输入流读取最多 len字节的数据为字节数组。

第二种方式:NIO:使用FileChannel复制:Java NIO包括transferFrom方法,根据文档应该比文件流复制的速度更快。

package 任务11IO流;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

/** * @author ${范涛之} * @Description * @create 2021-11-25 20:56 */
public class Test7 {

    private  static  void  copyFileUsingFileChannels(String sourse,String dest) throws IOException {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(sourse).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel,0,inputChannel.size());
        }finally {
            inputChannel.close();
            outputChannel.close();
        }

    }

    public static void main(String[] args) throws IOException {
        copyFileUsingFileChannels("H:\\bilbil\\毒液2.mp4","F:\\shipin\\复制版毒液2.mp4");
    }
}

运行结果:

这里说一下字符流:字符流只能读取文本不可以读取视频!

字符流:

package 任务11IO流;

import java.io.*;

/** * @author ${范涛之} * @Description * @create 2021-11-25 21:48 */
public class Test8 {

    private static void copyFileUsingFileStreams(String source, String dest) throws IOException {
        FileReader reader = null;
        FileWriter writer = null;

        try {
            reader = new FileReader(source);
            writer = new FileWriter(dest);
            char[] chs = new char[1024];
            int bytesRead;
            while ((bytesRead = reader.read(chs)) > 0) {
                writer.write(chs, 0, bytesRead);

            }

        } finally {
            reader.close();
            writer.close();
        }

    }

    public static void main(String[] args) throws IOException {
        copyFileUsingFileStreams("H:\\bilbil\\毒液2.mp4","F:\\shipin\\哈哈哈毒液2.mp4");
    }

}

这样的代码是错误的,因为只能复制文件文本:

package 任务11IO流;

import java.io.*;

/** * @author ${范涛之} * @Description * @create 2021-11-25 21:48 */
public class Test8 {

    private static void copyFileUsingFileStreams(String source, String dest) throws IOException {
        FileReader reader = null;
        FileWriter writer = null;

        try {
            reader = new FileReader(source);
            writer = new FileWriter(dest);
            char[] chs = new char[1024];
            int bytesRead;
            while ((bytesRead = reader.read(chs)) > 0) {
                writer.write(chs, 0, bytesRead);

            }

        } finally {
            reader.close();
            writer.close();
        }

    }

    public static void main(String[] args) throws IOException {
        copyFileUsingFileStreams("H:\\bilbil\\我爱佳佳.txt","F:\\shipin\\我超级爱佳佳.txt");
    }

}

运行结果:

相关文章

微信公众号

最新文章

更多

目录