多线程详解(一)

线程

线程是CPU调度和执行的单位。
(Main函数是主线程。)
在这里插入图片描述

线程的创建

在这里插入图片描述

继承Thread类的创建方式
  • 自定义线程类继承Thead类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
//创建线程方式一:继承Thread类,重写run()方法,调用start()开启线程
public class Test01 extends Thread {
    @Override
    public void run() {
        //run()方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在写代码----"+i);
        }
    }


    public static void main(String[] args) {

        //创建一个线程对象
        Test01 test01 = new Test01();
        test01.start();

        //main线程,主线程
        for (int i = 0; i < 200; i++) {
            System.out.println("我在学习多线程-----"+i);
        }
    }
}

总结:线程开启不一定立即执行,由CPU调度执行

通过多线程同步下载网图(导入commons-io.jar)

//练习Thread,实现多线程同步下载图片
public class Test02 extends Thread {

    private String name;
    private String url;

    public Test02(String url, String name){
        this.url = url;
        this.name = name;
    }


    @Override
    public void run() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println("下载了文件名为:"+name);
        //下载了文件名为:1.jpg
        //下载了文件名为:3.jpg
        //下载了文件名为:2.jpg
    }

    public static void main(String[] args) {
        Test02 t1 = new Test02("https://img-blog.csdnimg.cn/20200802130504287.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "1.jpg");
        Test02 t2 = new Test02("https://img-blog.csdnimg.cn/20200804015927727.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "2.jpg");
        Test02 t3 = new Test02("https://img-blog.csdnimg.cn/20200803000039156.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "3.jpg");

        t1.start();
        t2.start();
        t3.start();
    }
}

//下载器
class WebDownloader{
    public void downloader(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常,downloader方法出现问题");
        }
    }
}

实现Runnable接口

在这里插入图片描述

两者差别

在这里插入图片描述

火车票例子

//多个线程操作同一个对象例子:火车票
//发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱(初识并发问题)
public class Test04 implements  Runnable {

    //票数
    private int ticketNum = 10;

    @Override
    public void run() {
        while (true){
            if (ticketNum<=0){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--拿到了第--"+ticketNum--+"--票");
        }
    }

    public static void main(String[] args) {
        Test04 ticket = new Test04();

        new Thread(ticket,"小明").start();//Thread(对象,线程名)
        new Thread(ticket,"小李子").start();
        new Thread(ticket,"黄牛党").start();

    }
}
/*  控制台输出:
    小明--拿到了第--10--票
    小明--拿到了第--8--票
    小李子--拿到了第--9--票
    小明--拿到了第--7--票
    小明--拿到了第--5--票
    小明--拿到了第--4--票
    小明--拿到了第--3--票
    小明--拿到了第--2--票
    小明--拿到了第--1--票
    小李子--拿到了第--6--票
 */

模拟龟兔赛跑例子

//模拟龟兔赛跑
public class Race implements Runnable {

    //胜利者
    private static String winner;

    @Override
    public void run() {
        for (int i = 1; i < 1001; i++) {
            boolean flag = gameOver(i);
            if (flag){
                break;
            }
            if (Thread.currentThread().getName().equals("兔子") && i == 600){
                try {
                    System.out.println("兔子开始睡觉!");
                    Thread.currentThread().sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"--->跑了"+i+"米");
        }
    }

    public boolean gameOver(int distance){
        if (winner != null){
            return true;
        }else{
            if (distance>=1000){
                winner = Thread.currentThread().getName();
                System.out.println("winner is " + winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();

        new Thread(race, "乌龟").start();
        new Thread(race, "兔子").start();

    }
}

实现Callable接口

加粗样式

//线程创建方式三:实现callable接口
/*
    callable的好处
    1.可以定义返回值
    2.可以抛出异常
 */
public class Test06 implements Callable<Boolean> {
    private String name;
    private String url;

    public Test06(String url, String name){
        this.url = url;
        this.name = name;
    }
    @Override
    public Boolean call() throws Exception {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println("下载了文件名为:"+name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Test06 t1 = new Test06("https://img-blog.csdnimg.cn/20200802130504287.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "1.jpg");
        Test06 t2 = new Test06("https://img-blog.csdnimg.cn/20200804015927727.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "2.jpg");
        Test06 t3 = new Test06("https://img-blog.csdnimg.cn/20200803000039156.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hxMTgzMTg4NTk1NDE=,size_16,color_FFFFFF,t_70", "3.jpg");

        //创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> f1 = ser.submit(t1);
        Future<Boolean> f2 = ser.submit(t2);
        Future<Boolean> f3 = ser.submit(t3);
        //获取结果
        Boolean r1 = f1.get();
        Boolean r2 = f2.get();
        Boolean r3 = f3.get();
        //关闭服务
        ser.shutdown();
    }
}

(文章通过狂神说视频内容进行总结。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值