栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java面向对象之线程相关概念 和 线程基本使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java面向对象之线程相关概念 和 线程基本使用

文章目录
      • 1、多线程基础
        • 1.1、线程相关概念
          • 1.1.1、程序(program)
          • 1.1.2、进程
          • 1.1.3、线程
          • 1.1.4、其他相关概念
        • 1.2、线程基本使用
          • 1.2.1、创建线程的两种方式
          • 1.2.2、线程应用方式1 - 继承 Thread 类
          • 1.2.3、线程应用2 - 实现 Runnable 接口
          • 1.2.4、线程使用应用案例 - 多线程执行
          • 1.2.5、线程如何理解
          • 1.2.6、继承 Thread vs 实现 Runnable 的区别

1、多线程基础 1.1、线程相关概念 1.1.1、程序(program)

1.1.2、进程

1.1.3、线程

1.1.4、其他相关概念


1.2、线程基本使用 1.2.1、创建线程的两种方式

1.2.2、线程应用方式1 - 继承 Thread 类

package threaduse;

public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        // 创建 Cat 对象, 可以当做线程使用
        Cat cat = new Cat();
        // 源码
        
        cat.start();  // 启动线程 -> 最终会执行 cat 的 run 方法
        // cat.run();
        // run 方法就是一个普通的方法, 没有真正的启动一个线程, 就会把 run 方法执行完毕, 才向下执行
        // 说明: 当 main 线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行
        // 这时 主线程和子线程是交替执行
        System.out.println("主线程继续执行" + Thread.currentThread().getName());  // 名字 main
        for (int i = 0; i < 60; i++) {
            System.out.println("主线程i=" + i);
            // 让主线程休眠
            Thread.sleep(1000);
        }
    }
}

// 1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
// 2. 我们会重写 run 方法, 写上自己的业务代码
// 3. run Thread 类 实现了 Runnable 接口的 run 方法


class Cat extends Thread {
    int times = 0;

    @Override
    public void run() {  // 重写 run 方法, 写上自己的业务逻辑
        while (true) {
            // 该线程每隔 1 秒, 在控制台输出 “喵喵, 我是小猫咪”
            System.out.println("喵喵, 我是小猫咪 " + (++times) + " 线程名=" + Thread.currentThread().getName());
            // 让该线程休眠 1 秒 ctrl+alt+t
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (times == 80) break;  // 当 times 到 80, 退出 while, 这时线程也就退出
        }
    }
}

1.2.3、线程应用2 - 实现 Runnable 接口


package threaduse;

public class Thread02 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        // dog.start(); 这里不能调用 start
        // 创建了 Thread 对象, 把 dog 对象(实现 Runnable), 放入 Thread
        Thread thread = new Thread(dog);
        thread.start();

        Tiger tiger = new Tiger();
        ThreadProxy threadProxy = new ThreadProxy(tiger);
        threadProxy.start();
    }
}

class Animal {
}

class Tiger extends Animal implements Runnable {

    @Override
    public void run() {
        System.out.println("老虎嗷嗷叫...");
    }
}

// 线程代理类, 模拟了一个极简的 Thread 类
class ThreadProxy implements Runnable {  // 你可以把 Proxy 类当做 ThreadProxy
    private Runnable target = null;  // 属性, 类型是 Runnable

    @Override
    public void run() {
        if (target != null) {
            target.run();  // 动态绑定(运行类型 Tiger)
        }
    }

    public ThreadProxy(Runnable target) {
        this.target = target;
    }

    public void start() {
        start0();  // 这个方法时真正实现多线程方法
    }

    public void start0() {
        run();
    }
}

class Dog implements Runnable {  // 通过实现 Runnable 接口, 开发线程
    int count = 0;

    @Override
    public void run() {  // 普通方法
        while (true) {
            System.out.println("小狗汪汪叫..hi " + (++count) + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10) break;
        }
    }
}
1.2.4、线程使用应用案例 - 多线程执行

package threaduse;

public class Thread03 {
    public static void main(String[] args) {
        T1 t1 = new T1();
        T2 t2 = new T2();
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.start();
        thread2.start();
    }
}

class T1 implements Runnable {
    int count = 0;

    @Override
    public void run() {
        while (true) {
            // 每隔 1 秒输出 “hello,world”, 输出 10次
            System.out.println("hello,world " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10) break;
        }
    }
}

class T2 implements Runnable {
    int count = 0;

    @Override
    public void run() {
        while (true) {
            // 每隔 1 秒输出 “hi”, 输出 5 次
            System.out.println("hi " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 5) break;
        }
    }
}
1.2.5、线程如何理解


1.2.6、继承 Thread vs 实现 Runnable 的区别


package threaduse;


public class SellTicket {
    public static void main(String[] args) {
        // 测试

        System.out.println("=== 继承Thread方式来售票 ===");
        SellTicket01 sellTicket01 = new SellTicket01();
        SellTicket01 sellTicket02 = new SellTicket01();
        SellTicket01 sellTicket03 = new SellTicket01();
        // 这里我们会出现超卖
        sellTicket01.start();  // 启动售票线程
        sellTicket02.start();  // 启动售票线程
        sellTicket03.start();  // 启动售票线程


        System.out.println("=== 使用实现接口方式来售票 ===");
        SellTicket02 sellTicket021 = new SellTicket02();
        new Thread(sellTicket021).start();  // 第 1 个线程-窗口
        new Thread(sellTicket021).start();  // 第 2 个线程-窗口
        new Thread(sellTicket021).start();  // 第 3 个线程-窗口

        // 结论: 这两种方式都会出现超卖的现象
    }
}

class SellTicket01 extends Thread {
    private static int ticketNum = 100;  // 让多个线程共享 ticketNum

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束...");
                break;
            }

            // 休眠50毫秒, 模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));
        }
    }
}

// 实现接口方式
class SellTicket02 implements Runnable {
    private int ticketNum = 100;  // 让多个线程共享 ticketNum

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束...");
                break;
            }

            // 休眠50毫秒, 模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));
        }
    }
}

结论:这两种方式都会出现超卖的现象

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/685870.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号