• 多线程学习1--------线程的创建


    多线程简介:

    在学习多线程之前,首先了解一下什么是多线程?

    多任务
    多任务比如说一个人他可以边吃饭,边玩手机,看似一起发生的行为,但其实是上一秒在吃饭,下一秒在玩手机,本质上同一时间只做一件事情。
    进程Process
    进程就是程序执行的过程,他是一个动态的概念,一个进程中可以包含若干个线程,至少要有一个线程,否则毫无意义。他是操作系统进行资源分配的最小单位,每启动一个进程,操作系统就会为它分配一个独立的内存空间。
    线程Thread
    线程是CPU调度和执行的单位,一个线程就是一个任务执行的一次执行过程,线程不占内存空间,他是包含在进程内存空间里面的。因为一个CPU同一时间只能做一件事情,所以真正的多线程是指有多个CPU,即多核,如服务器。在程序运行时,即使没有创建线程,后台也会有多个线程,如主线程(用户线程),gc线程(守护线程)。

    线程创建

    方式一:继承Thread类

    步骤:继承Thread类,重写run()方法,在主线程(main()函数)里创建该类对象,通过该对象调用start()方法开启线程。
    示例:模拟多线程执行任务
    package com.xct.test;
    
    public class Test1 extends Thread {
    
        @Override
        public void run() {
            //重写run方法
            for (int i = 0; i < 200; i++) {
                System.out.println("我在敲代码"+i);
            }
        }
    
        public static void main(String[] args) {
            //在主线程里面创建线程对象
            Test1 test1 = new Test1();
            test1.start();
    
            //执行程序的入口,主线程
            for (int i = 0; i < 800; i++) {
                System.out.println("我在学习"+i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    注意:线程开启不一定立即执行,由CPU调度执行。

    方式二:实现Runnable接口

    步骤:实现Runnable接口=》重写run()方法,在主线程里创建该类对象,再创建线程Thread对象,通过线程对象调用start()方法开启线程(代理)。
    示例:实现多线程下载图片(准备工作:百度下载commons-io.2.6.jar包)
    package com.xct.test;
    
    import org.apache.commons.io.FileUtils;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    
    //实现多线程下载图片
    public class Test2 extends Thread{
        private String url;
        private String name;
    
        public Test2(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);
        }
    
        public static void main(String[] args) {
            Test2 t1 = new Test2("https://img0.baidu.com/it/u=1472391233,99561733&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666544400&t=d5daee453462255eb4d0fe7c29511d87","1.jpg");
            Test2 t2 = new Test2("https://img0.baidu.com/it/u=1472391233,99561733&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666544400&t=d5daee453462255eb4d0fe7c29511d87","2.jpg");
            Test2 t3 = new Test2("https://img0.baidu.com/it/u=1472391233,99561733&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666544400&t=d5daee453462255eb4d0fe7c29511d87","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异常,图片下载错误");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    小结

    继承Thread类
    启动线程:子类对象.start()
    不建议使用:避免OOP单继承局限性
    实现Runnable接口
    启动线程:传入目标对象+Thread对象.start()
    推荐使用:避免单继承局限性,灵活方便,方便同一个对象呗多个线程使用。

    方式三:实现Callable接口

    步骤:实现Callable接口=》重写call<>方法,在主线程中创建实现类对象,创建执行服务,提交执行,获取结果,关闭服务。
    好处:可以定义返回值,可以抛出异常,该方式了解即可。
    示例:实现多线程执行任务
    package com.xct.test;
    
    import java.util.concurrent.*;
    
    //实现callable接口
    public class Test6 implements Callable<Boolean> {
        @Override
        public Boolean call() {
            for (int i = 0; i < 500; i++) {
                System.out.println("我在学习"+i);
            }
            return true;
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            for (int i = 0; i < 600; i++) {
                System.out.println("我在打游戏"+i);
            }
    
            Test6 t1 = new Test6();
            Test6 t2 = new Test6();
            Test6 t3 = new Test6();
            //创建执行服务
            ExecutorService ser = Executors.newFixedThreadPool(3);
            //提交执行
            Future<Boolean> r1 = ser.submit(t1);
            Future<Boolean> r2 = ser.submit(t2);
            Future<Boolean> r3 = ser.submit(t3);
            //获取结果
            boolean rs1 = r1.get();
            boolean rs2 = r2.get();
            boolean rs3 = r3.get();
    
            System.out.println(rs1);
            System.out.println(rs2);
            System.out.println(rs3);
            //关闭服务
            ser.shutdownNow();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    练习

    示例:买火车票(会发生并发问题,后期解决)
    package com.xct.test;
    
    //买火车票
    public class Test4 implements Runnable{
    
        private Integer ticket = 10;
        @Override
        public void run() {
            while (true){
                if (ticket<=0){
                    break;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"买到了第"+ticket--+"票");
            }
        }
    
        public static void main(String[] args) {
            Test4 test4 = new Test4();
    
            new  Thread(test4,"小明").start();
            new  Thread(test4,"老师").start();
            new  Thread(test4,"黄牛").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    示例:龟兔赛跑
    package com.xct.test;
    //模拟龟兔赛跑
    public class Test5 implements Runnable{
    
        //设置一个全局的胜利者
        private static String winner;
        @Override
        public void run() {
    
            for (int i = 0; i <= 100; i++) {
    
                //模拟兔子休息
                if(Thread.currentThread().getName().equals("兔子")&& i%10==0){
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
                //判断比赛是否结束
                boolean flag = getWinner(i);
                if(flag){
                    break;
                }
    
                System.out.println(Thread.currentThread().getName()+"跑了第"+i+"步");
            }
        }
    
        //模拟比赛结束
        public boolean getWinner(int step) {
            //判断此时是否有胜利者
            if (winner != null) {
                return true;
            } else {
                if (step == 100) {
                    //给全局winner赋值
                    winner = Thread.currentThread().getName();
                    System.out.println("winner是" + winner);
                    return true;
                }
            }
            return false;
        }
    
        public static void main(String[] args) {
            Test5 test5 = new Test5();
    
            new Thread(test5,"兔子").start();
            new Thread(test5,"乌龟").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
  • 相关阅读:
    对加密世界的经济误解:现金是储蓄?稀缺性创造价值?
    java毕业设计电影评论网站系统(附源码、数据库)
    前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 第三章 项目创建
    MySQL
    c++ 常用STL 之vector
    树莓派4B配置ubuntu18.04.5
    2022年11月30日 Fuzzy C-Means学习笔记
    Unity——模拟AI视觉
    Java学习笔记(二十五)
    考公考编内心历程
  • 原文地址:https://blog.csdn.net/m0_57082679/article/details/127464859