【从零开始重学Java】第12天 线程

传送门

从零开始重学Java 第0天
从零开始重学Java 第1天 Java概述
从零开始重学Java 第2天 标识符和数据类型
从零开始重学Java 第3天 表达式和流程控制语句
从零开始重学Java 第4天 数组、向量和字符串
从零开始重学Java 第5天 对象和类
从零开始重学Java 第6天 异常
从零开始重学Java 第7天 高级特性
从零开始重学Java 第8_9_10天 图形界面、Swing、Applet
从零开始重学Java 第11天 数据流
从零开始重学Java 第12天 线程
从零开始重学Java 第13天 线程

线程

线程和多线程

线程的概念

线程的结构

  • Cpu 虚拟CPU
  • Code 代码逻辑
  • Data 传入的处理数据

线程的状态

注意进程状态和Java的线程状态是有区别的
进程的状态

Java线程的状态 图解Java线程的6种状态及切换

Java线程的状态
Java线程的状态图

创建线程

创建线程的方法一——继承Thread类

创建线程的方法二——实现Runnable接口

关于两种创建线程的方法讨论

线程的启动

正式项目请使用统一调配的线程池来管理多线程

线程的调度

线程的基本控制

结束线程

检查线程

挂起线程

同步问题

volatile只能解决多线程读的问题不能解决多线程写的问题
synchronized锁太重而且不够灵活
使用改进的ReentrantLock可重入锁
如果是非单体项目,建议借助Redis加锁

线程间的通信

线程间的资源互斥共享

对象的锁定标志

只有wait和stop会主动释放锁,join、sleep、yield都不会释放锁

同步方法

死锁

线程交互——wait()和notify()

notify和notifyAll有什么区别notify和notifyAll

问题的提出

解决方法

守护线程

垃圾回收GC(Garbage Collection)线程就是一个典型的守护线程

综合应用

第十二章习题

  • 什么叫做线程?什么叫做多线程?Java的多线程有何特点?

线程是操作系统中能够执行并独立运行的最小单位。它是进程中的一个实体,每个线程都有自己的任务和执行路径

多线程(Multithreading)是指在一个程序中同时执行多个线程,每个线程处理不同的任务,从而提高程序的效率和性能

Java的多线程,并发性、共享内存、线程调度、线程同步、线程生命周期管理、线程安全

  • sleep和yield的区别

sleep()方法是控制线程暂停一段时间的有效方式,而yield()方法是一种线程调度器的提示,用于启发调度器让出CPU给其他线程,并不能保证其他线程一定会被执行

  • Java如何调度线程

Java使用线程调度器来控制线程的执行顺序和优先级。线程调度器是操作系统的一部分,负责在不同线程之间分配CPU时间片,使得每个线程都有机会执行自己的任务

  • 领会Java中的线程间交互机制,完成以下程序,创建两个Thread子类,第一个用run()方法启动,并捕获第二个Thread对象的句柄,然后调用wait()。第二个类的run()方法几秒后为第一个线程调用notifyAll(),使第一个线程打印消息

synchronized太重了,现在更习惯使用轻量的ReentrantLock控制同步,或者配合CountDownLatch更进一步细化控制

//synchronized
    public static void main(String[] args) {
        Thread r1 = new FirstThread();
        Thread r2 = new SecondThread(r1);
        r1.start();
        try {
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        r2.start();

        try {
            Thread.sleep(10000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class FirstThread extends Thread {

        @Override
        public void run() {
            System.out.println(LocalTime.now() + " r1 开始");
            synchronized(this) {
                try {
                    System.out.println(LocalTime.now() + " r1 wait()");
                    // 等待第二个线程调用notifyAll()
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(LocalTime.now() + " r1 结束");
        }
    }
    static class SecondThread extends Thread {

        private final Thread otherThread;

        public SecondThread(Thread otherThread) {
            this.otherThread = otherThread;
        }

        @Override
        public void run() {
            System.out.println(LocalTime.now() + " r2 开始");
            try {
                System.out.println(LocalTime.now() + " r2 3秒后 唤醒r1");
                // 等待 3 秒后唤醒第一个线程
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized(this.otherThread) {
                System.out.println(LocalTime.now() + " r2 唤醒r1");
                this.otherThread.notifyAll();
            }
            System.out.println(LocalTime.now() + " r2 结束");
        }

    }
//join
    private static Thread r1;
    private static Thread r2;

    public static void main(String[] args) {
        r1 = new Thread(() -> {
            try {
                Thread.sleep(100);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(LocalTime.now() + " 我是r1 等r2执行完后再执行");
            try {
                System.out.println("r1 调用r2.join");
                r2.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(LocalTime.now() + " r1 Hello world 1");
        });
        r2 = new Thread(() -> {
            try {
                Thread.sleep(100);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(LocalTime.now() + " 我是r2 虽然启动晚,但要比r1先执行完成");
            try {
                System.out.println(LocalTime.now() + " r2 Hello world 2");
                Thread.sleep(3000);
                System.out.println(LocalTime.now() + " r2 执行完成了 轮到r1");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });


        r1.start();
        try {
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        r2.start();

        try {
            Thread.sleep(10000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
// ReentrantLock
        ReentrantLock lockObj = new ReentrantLock();
        Condition condition = lockObj.newCondition();
        Thread r1 = new Thread(() -> {
            System.out.println(LocalTime.now() + " 我是r1 等r2执行完后再执行");
            try {
                lockObj.lock();
                condition.await();
                System.out.println(LocalTime.now() + " r1 Hello world 1");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                lockObj.unlock();
            }
        });
        Thread r2 = new Thread(() -> {
            System.out.println(LocalTime.now() + " 我是r2 虽然启动晚,但要比r1先执行完成");
            try {
                lockObj.lock();
                System.out.println(LocalTime.now() + " r2 Hello world 2");
                Thread.sleep(3000);
                System.out.println(LocalTime.now() + " r2 唤醒 r1");
                condition.signalAll();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                lockObj.unlock();
            }
        });

        r1.start();
        try {
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        r2.start();

        try {
            Thread.sleep(10000);
        }catch (Exception e){
            e.printStackTrace();
        }
//CountDownLatch
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Thread r1 = new Thread(() -> {
            System.out.println(LocalTime.now() + " 我是r1 等r2执行完后再执行");
            try {
                countDownLatch.await();
                System.out.println(LocalTime.now() + " r1 Hello world 1");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        Thread r2 = new Thread(() -> {
            System.out.println(LocalTime.now() + " 我是r2 虽然启动晚,但要比r1先执行完成");
            System.out.println(LocalTime.now() + " r2 Hello world 2");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(LocalTime.now() + " r2 唤醒 r1");
            countDownLatch.countDown();
        });

        r1.start();
        try {
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        r2.start();

        try {
            Thread.sleep(10000);
        }catch (Exception e){
            e.printStackTrace();
        }
  • 单例模式,保证线程安全的构造方法
public class MySingleton {

    private static MySingleton instance = new MySingleton();

    private MySingleton(){}

    public static MySingleton getInstance() {
        return instance;
    }
}

public class MySingleton {

    private volatile static MySingleton instance = null;

    private MySingleton(){}
    
    public static MySingleton getInstance(){
        if(instance == null){
            synchronized (MySingleton.class) {
                if(instance == null){
                    instance = new MySingleton();
                }
            }
        }
        return instance;
    }
}
posted @ 2024-01-17 16:56  迷路的哨兵甲  阅读(5)  评论(0编辑  收藏  举报