多线程、多线程同步代码块、线程安全与锁、单线程下载与多线程下载、多线程卖票案例、获取服务器文件大小

01_多线程概述

             进程:应用程序(可执行文件)
             一个进程可以有多个线程
             线程: 进程的执行路径\单元
             
             单线程:进程只有一个可执行路径,按照步骤一步一步执行,前面的步骤没有执行完,不会执行后面的步骤
             多线程:进程有多个可执行路径
             
             例子:
                 洗水壶    接水        烧水        洗茶壶    洗茶杯    拿茶叶    喝水


02_多线程并行和并发的区别:

             多线程并行:多条线程同时执行,需要多核cpu
             多线程并发:多条线程同时请求cpu,但是交替执行,由于cpu切换速度非常快,所以感觉像多线程并行


 03_多线程的第一种实现方式

            1.创建一个类继承Thread类
            2.重写Thread类里面的run()方法,把多线程要执行的代码放入run()方法里面
            3.创建该类的对象
            4.调用start()方法启动线程


04_多线程的第二种实现方式
        /*
             1.创建一个类实现Runnable接口
             2.重写run()方法,把多线程要执行的代码放入到run()方法里面
             3.创建一个Thread对象,把实现Runnable接口类的对象传入进来
             4.调用start()方法启动线程
         */

    第三种实现方式: 通过匿名内部类
     Thread th = new Thread(new Runnable() {
            
            @Override
            public void run() {
                for(int i = 0 ;i<200;i++) {
                    System.out.println("i...这是第"+i+"次循环");
                }
                
            }
        });
        th.start();


05_多线程两种实现方式之间的区别
 * 继承Thread类:
     * 好处: 代码相对比较简单. 因为是直接继承Thread类, 所以可以直接使用Thread类中的方法.
     * 弊端: 扩展性差. 因为Java中类与类之间的继承只支持单继承, 不支持多继承. 类继承了Thread类,就不能在继承别的类了.
 * 实现Runnable接口:
     * 好处: 扩展性强.
     * 弊端: 代码相对比较繁琐.


06_多线程常用的方法
    currentThread(): 获取当前线程
    setName()  修改线程的名字
    getName()  获取线程的名字
    start()   启动线程
    sleep()  暂停线程执行


07_多线程同步代码块
        // 多条线程同时请求一段相同的代码的时候,就会出现数据不安全的情况
        // 怎么解决? 加锁  同步
        // 同步代码块: 有一段代码需要加锁,不希望别人打扰
        // 同步方法:当一个方法里面 的所有代码都需要加锁的时候
        /*
             同步代码块的锁对象:
                 1.锁对象可以是任意类型的对象
                 2.锁对象是唯一的
                 3.类的字节码文件对象 只有一个
         */

    @Override
    public void run() {
        synchronized (MyThread.class) {
            System.out.println(getName()+":打开厕所门");
            System.out.println(getName()+":关闭厕所门");
            System.out.println(getName()+":脱裤子");
            System.out.println(getName()+":蹲下");
            System.out.println(getName()+":用力...");
            System.out.println(getName()+":擦屁股");
            System.out.println(getName()+":穿裤子");
            System.out.println(getName()+":冲厕所");
            System.out.println(getName()+":打开厕所门");
            System.out.println(getName()+":关闭厕所门");
            System.out.println(getName()+":洗手,高高兴兴的走了");
        }
    }

08 同步方法

        同步方法: 当整个方法里面的代码都需要加锁的时候
                 非静态同步方法:
                     锁对象: this
                 静态同步方法:
                     锁对象:该类.class

09 沏茶案例
    public void 烧水() {
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                try {
                    Thread.sleep(15000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("水烧好了");
                
            }
        }).start();
    }
    

10_ 多线程卖票的案例


   public static int tickets = 100;
    @Override
    public void run() {
        // 因为不知道每个窗口要卖多少张票,所以用循环
        while(true) {// 线程1 1 线程2  0
            synchronized (MyThread.class) {
                if(tickets < 1) {//线程1 1    线程2 1     线程3 1     线程4 1
                    break;
                }
                try {
                    Thread.sleep(100);// 线程1 睡了  线程2 睡了  线程3 睡了 线程4 睡了
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 卖票的过程    线程1 醒了 线程2 醒了  线程3醒了  线程4 醒了
                System.out.println(getName()+"...这是第"+tickets+"票");// 线程1 1  线程2 0 线程3  -1 线程4 -2
                tickets--;
            }
        }
    }


11 单线程下载器下载服务器上的文件

    /**
     * 单线程下载服务器文件
     * @param srcPath
     * @param destPath
     */
    public static void singleThreadDownLoadFile(String srcPath,String destPath) {

        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(srcPath);
            // 根据url对象得到字节输入流对象
            is = url.openStream();
            // 创建一个字节输出流对象
            fos = new FileOutputStream(destPath);
            // 定义一个变量,用来存储读取到的字节数据
            int len = 0;
            // 循环读取
            while ((len = is.read()) != -1) {
                // 写入数据
                fos.write(len);
            }
        } catch (Exception e) {
            System.out.println("读取失败,出现了异常");
        }finally {
            // 关闭流
            try {
                if(is != null) {
                    is.close();
                }
            } catch (IOException e) {
                System.out.println("关闭输入流失败");
            }finally {
                try {
                    fos.close();
                } catch (IOException e) {
                    System.out.println("关闭输出流失败");
                }
            }
            
        }
        System.out.println("搞定");
    }


12_ 单线程分段下载器下载服务器上的文件
        
    /**
     * 单线程指定字节下载服务器文件
     * @param srcPath
     * @param destPath
     * @param start 起始字节
     * @param end   结束字节
     */
    public static void singleThreadDownLoadPartFile(String srcPath,String destPath,int start,int end) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(srcPath);
            //得到连接对象   设置请求属性
            URLConnection uc = url.openConnection();
            uc.setRequestProperty("Range", "bytes="+start+"-"+end);
            // 通过uc连接对象 ,可以得到字节输入流对象
            is = uc.getInputStream();
            // 创建输出流对象
            fos = new FileOutputStream(destPath);
            // 定义一个变量用来存储读取到的字节数据
            int len = 0;
            // 循环读取
            while((len = is.read()) != -1) {
                // 写入文件
                fos.write(len);
            }

        } catch (IOException e) {
            System.out.println("出现了异常");
        }finally {
            // 关闭流
            try {
                if(is != null) {
                    is.close();
                }
            } catch (IOException e) {
                System.out.println("关闭输入流失败");
            }finally {
                try {
                    if(fos != null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    System.out.println("关闭输出流失败");
                }
            }
            
        }
    }
}


13_合并文件
    
    public static void mergeFile(String srcPath,String destPath) {
        File file = new File(srcPath);
        File[] listFiles = file.listFiles();
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(destPath);
            if(listFiles != null) {
                for(File file2 :  listFiles) {
                    if(file2.isFile() && file2.getName().endsWith(".temp")) {
                        // IO流的代码
                        FileInputStream fis = new FileInputStream(file2);
                        
                        int len = 0;
                        while((len = fis.read()) != -1) {
                            fos.write(len);
                        }
                        fis.close();
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("出现了异常");
        }finally {
            
            try {
                if(fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


14_多线程分段下载服务器文件
        

public class MyThread  extends Thread{
    public String srcPath;
    public int start;
    public int end;
    public String destPath;
    
    public MyThread(String srcPath, int start, int end, String destPath) {
        super();
        this.srcPath = srcPath;
        this.start = start;
        this.end = end;
        this.destPath = destPath;
    }


    @Override
    public void run() {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(srcPath);
            //得到连接对象   设置请求属性
            URLConnection uc = url.openConnection();
            uc.setRequestProperty("Range", "bytes="+start+"-"+end);
            // 通过uc连接对象 ,可以得到字节输入流对象
            is = uc.getInputStream();
            // 创建输出流对象
            fos = new FileOutputStream(destPath);
            // 定义一个变量用来存储读取到的字节数据
            int len = 0;
            // 循环读取
            while((len = is.read()) != -1) {
                // 写入文件
                fos.write(len);
            }

        } catch (IOException e) {
            System.out.println("出现了异常");
        }finally {
            // 关闭流
            try {
                if(is != null) {
                    is.close();
                }
            } catch (IOException e) {
                System.out.println("关闭输入流失败");
            }finally {
                try {
                    if(fos != null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    System.out.println("关闭输出流失败");
                }
            }
            
        }
    }
}

 15_获取服务器文件大小
    
    public static int getFileSize(String path) {
        int len = 0;
        try {
            URL url = new URL(path);
            URLConnection uc = url.openConnection();
            len = uc.getContentLength();
        } catch (Exception e) {
            System.out.println("计算大小出现异常");
        }
        return len;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值