☀️苏州程序大白一文解析Java多线程☀️《❤️记得收藏❤️》

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: ☀️苏州程序大白一文解析Java多线程☀️《❤️记得收藏❤️》

☀️苏州程序大白一文解析Java多线程☀️《❤️记得收藏❤️》


目录


🏳️‍🌈开讲啦!!!!🏳️‍🌈苏州程序大白🏳️‍🌈


🌟博主介绍

基本概念

线程的相关Api

多线程和单线程

线程的创建

继承Thread类

实现Runnable接口

实现callable接口

线程的生命周期

线程同步

线程死锁

线程通信


🌟作者相关的文章、资源分享🌟


目录


🏳️‍🌈开讲啦!!!!🏳️‍🌈苏州程序大白🏳️‍🌈


ed11559beec041ed8c0a575bce01760f.png


🌟博主介绍


💂 个人主页:苏州程序大白


🤟作者介绍:中国DBA联盟(ACDU)成员,CSDN全国各地程序猿(媛)聚集地管理员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室。


💬如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)和C#、Halcon、python+opencv、VUE、各大公司面试等一些订阅专栏哦


🎗️ 承接各种软件开发项目


💅 有任何问题欢迎私信,看到会及时回复


👤 微信号:stbsl6,微信公众号:苏州程序大白


🎯 想加入技术交流群的可以加我好友,群里会分享学习资料


基本概念


程序:是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象。


进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,有它自身的产生,存在和消亡的过程。-------生命周期。


线程:进程中的一个任务,是一个程序内部的一条执行路径


即:线程《 进程(一个进程可以有多个线程)


程序:静态的代码


进程:动态执行的程序。


线程:进程中要同时干几件事时,每一件事的执行路径成为线程。


并行:多个CPU同时执行多个任务,比如 : 多个线程一起执行。


并发:一个CPU(采用时间片)同时执行多个任务,比如:多个线程间隔执行。


线程的相关Api


    Thread thread = new Thread();
        thread.start();          //启动当前线程,调用当前线程中的run方法,注意并不是立即执行,只是进入就绪状态等待资源的调用
        thread.sleep(5000);    //休眠5s
        thread.getName();        //获取当前线程的名字,也可以Thread.currentThread().getName()
        thread.setName("");      //设置当前线程的名字,也可以Thread.currentThread().setName()
        Thread.currentThread();  //返回当前线程
        Thread.yield();          //主动释放当前线程的执行权
        thread.join();           //执行过程中插入该线程,只有插入线程执行完毕,主线程才会继续执行
        thread.isAlive();        //判断线程是否存活
        thread.setPriority(1);   //设置线程的优先级,有三个等级: MAX_PRIORITY:10 MIN_PRIORITY:1 NORM_PRIORITY:5
        thread.getPriority();    //获取线程的优先级
        thread.setDaemon(false); //设置守护线程,主线程结束守护线程也结束 false,true
        thread.isDaemon();       //判断是否是守护线程
        thread.wait();           //强行停止当前线程,进入阻塞状态
        thread.notify();         //唤醒一个被wait停止线程的线程
        thread.notifyAll();      //唤醒所有被wait停止的停止线程

多线程和单线程


单线程示例:  


public class SingleThread {
    public void method1(){
        System.out.println("SingleThread.method1");
    }
    public void method2(){
        method1();
    }
    public static void main(String[] args) {
    //一条线执行
        SingleThread single = new SingleThread();
        single.method2();
    }
}


多线程示例:  


public class ManyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    public static void main(String[] args) {
        ManyThread manyThread = new ManyThread();
        new Thread(manyThread,"线程A").start();
        new Thread(manyThread,"线程B").start();
    }
}


线程的创建


继承Thread类


1、创建一个继承Thread类的子类 (通过ctrl+o 快速找到run方法)。


2、重写Thread类的run()方法。


3、创建Thread子类的对象。


4、通过此对象调用start()方法。


public class ManyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    public static void main(String[] args) {
        ManyThread manyThread = new ManyThread();
        manyThread.start();
    }
}


实现Runnable接口


1、创建一个实现了Runnab

le接口的类。


2、实现类去实现Runnable中的抽象方法:run()。


3、创建实现类的对象。


4、将此对象作为参数传递到Thread类中的构造器中,创建Thread类的对象。


5、通过Thread类的对象调用start()。


public class TestRunable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
    public static void main(String[] args) {
        TestRunable runable = new TestRunable();
        new Thread(runable).start();
    }
}


比较创建线程的两种方式:  


开发中,优先选择实现Runable接口的方式。


原因:  


1、适合多个相同的程序代码的线程去处理同一个资源。


2、可以避免java中的单继承的限制。


3、增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。


联系:Thread也是实现Runnable接口,两种方式都需要重写run()方法,将线程要执行的逻辑声明在run中。


实现callable接口

1、创建一个实现了callable接口的类。


2、实现call方法,将此线程需要执行的操作声明在call()中。


3、创建实现类的对象。


4、将callable接口实现类的对象作为传递到FutureTask的构造器中,创建FutureTask的对象。


5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start方法启动(调用FutureTask对象的get方法获取返回值)。


public class TestCallable implements Callable {
    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
        return "线程执行完毕";
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable callable = new TestCallable();
        FutureTask<String> task = new FutureTask<String>(callable);
        new Thread(task).start();
        System.out.println(task.get());
    }
}


线程的生命周期


0857dde8e7454655be213297d9d271c7.png


1、新建状态(New):新创建了一个线程对象。


2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。


3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。


4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:


(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。


(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。


(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。


5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


线程同步


线程安全问题:


线程安全问题是指,多个线程对同一个共享数据进行操作时,线程没来得及更新共享数据,从而导致另外线程没得到最新的数据,从而产生线程安全问题。


解决方法:使用同步监视器(锁)synchronized 、lock(ReentrantLock)


同步代码块:    


public class ManyThread extends Thread{
    private static int count = 100;  //一百张票,共同的资源
    @Override
    public void run() {
        //同步代码块
        synchronized (this){
            while (count > 0) {
                try {
                    Thread.sleep(1000);  //休眠一秒
                    System.out.println(Thread.currentThread().getName()+"卖出了一张票,余票"+(--count));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        ManyThread manyThread = new ManyThread();
        new Thread(manyThread,"窗口1").start();
        new Thread(manyThread,"窗口2").start();
        new Thread(manyThread,"窗口3").start();
        new Thread(manyThread,"窗口4").start();
    }
}


同步方法:    


public class ManyThread extends Thread{
    private static int count = 100;  //一百张票,共同的资源
    //创建ReentrantLock锁对象
    private Lock lock = new ReentrantLock();
    //使用synchronized同步方法
    @Override
    public synchronized void run() {
            while (count > 0) {
                try {
                    Thread.sleep(1000);  //休眠一秒
                    System.out.println(Thread.currentThread().getName()+"卖出了一张票,余票"+(--count));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    }
    public static void main(String[] args) {
        ManyThread manyThread = new ManyThread();
        new Thread(manyThread,"窗口1").start();
        new Thread(manyThread,"窗口2").start();
        new Thread(manyThread,"窗口3").start();
        new Thread(manyThread,"窗口4").start();
    }
}


lock锁的使用:    


public class ManyThread extends Thread{
    private static int count = 100;  //一百张票,共同的资源
    //创建ReentrantLock锁对象
    private Lock lock = new ReentrantLock();
    @Override
    public void run() {
            lock.lock();
            while (count > 0) {
                try {
                    Thread.sleep(1000);  //休眠一秒
                    System.out.println(Thread.currentThread().getName()+"卖出了一张票,余票"+(--count));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            lock.unlock();
    }
    public static void main(String[] args) {
        ManyThread manyThread = new ManyThread();
        new Thread(manyThread,"窗口1").start();
        new Thread(manyThread,"窗口2").start();
        new Thread(manyThread,"窗口3").start();
        new Thread(manyThread,"窗口4").start();
    }
}


Synchronized与lock的区别


相同:二者都可以解决线程安全问题。


不同:synchronized机制在执行完相应的代码逻辑以后,自动的释放同步监视器lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())(lock的方式更为灵活)。


线程死锁

 理解:两个人过独木桥,走到桥中央谁都不让谁。    


public class Deadlock {
    public static void main(String[] args) {
        //准备两把锁
        Object o1 = new Object();
        Object o2 = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                //先拿第一把锁
                synchronized (o1){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("o1过了一半");
                    synchronized (o2){
                        System.out.println("o1过完桥了");
                    }
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                //先拿第一把锁
                synchronized (o2){
                    System.out.println("o2过了一半");
                    synchronized (o1){
                        System.out.println("o2过完桥了");
                    }
                }
            }
        }).start();
    }
}


解决死锁的办法:    


1、减少同步共享变量。


2、采用专门的算法,多个线程之间规定先后执行的顺序,规避死锁问题。


3、减少锁的嵌套。


线程通信


线程间通信可以通过共享变量+wait()+notify()来实现。


wait()将线程进入阻塞状态,notify()将线程唤醒,notifyAll()唤醒所有的线程。


使用前提:这三个方法均只能使用在同步代码块或者同步方法中:


wait 和 sleep的区别?


二者都会让线程进入阻塞状态,有以下区别:


wait是Object的方法 sleep是Thread的方法。


wait会立即释放锁 sleep不会释放锁。


wait后线程的状态是Watting sleep后线程的状态为 Time_Waiting。


生产者消费者模型:指的是有生产者来生产数据,消费者来消费数据,生产者生产满了就不生产了,通知消费者取,等消费了再进行生产。


public class Test {
    public static void main(String[] args) {
        Factory msg = new Factory();
        Produce produce = new Produce(msg);
        Consumer consumer = new Consumer(msg);
        new Thread(produce,"工厂A").start();
        new Thread(produce,"工厂B").start();
        new Thread(produce,"工厂C").start();
        new Thread(consumer,"店铺D").start();
        new Thread(consumer,"店铺E").start();
    }
}
/**
 * 消息
 */
class Factory{
     int count = 0;   //库存
     //生产一台电脑
     public synchronized void add() throws InterruptedException {
         while (count <= 10){
             //设置最大库存数
             if (count >= 10){
                 wait();
                 //防止溢出
                 continue;
             }
             Thread.sleep(1000);
             System.out.println(Thread.currentThread().getName()+"生产了一台电脑,库存:"+(++count));
             notifyAll();
         }
     }
     //消费一台电脑
     public synchronized void pull() throws InterruptedException {
        while (count >= 0){
            if (count <= 0){
                wait();
                continue;
            }
            Thread.sleep(500);
            System.out.println(Thread.currentThread().getName()+"消费了一台电脑,库存:"+(--count));
            notifyAll();
        }
     }
}
/**
 * 生产者
 */
class Produce implements Runnable{
    private Factory factory;
    public Produce(Factory factory) {
        this.factory = factory;
    }
    @Override
    public void run() {
        try {
            factory.add();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 消费者
 */
class Consumer implements Runnable{
    private Factory factory;
    public Consumer(Factory factory) {
        this.factory = factory;
    }
    @Override
    public void run() {
        try {
            factory.pull();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

58084b783cf448a1be3a2feebbab9b5b.gif

🌟作者相关的文章、资源分享🌟

🌟让天下没有学不会的技术🌟


学习C#不再是难问题


🌳《C#入门到高级教程》🌳


有关C#实战项目


👉C#RS232C通讯源码👈


👉C#委托数据传输👈


👉C# Modbus TCP 源代码👈


👉C# 仓库管理系统源码👈


👉C# 欧姆龙通讯Demo👈


👉C#+WPF+SQL目前在某市上线的车管所摄像系统👈


👉2021C#与Halcon视觉通用的框架👈


👉2021年视觉项目中利用C#完成三菱PLC与上位机的通讯👈


👉VP联合开源深度学习编程(WPF)👈


✨有关C#项目欢迎各位查看个人主页✨


🌟机器视觉、深度学习🌟


学习机器视觉、深度学习不再是难问题


🌌《Halcon入门到精通》🌌


🌌《深度学习资料与教程》🌌


有关机器视觉、深度学习实战


👉2021年C#+HALCON视觉软件👈


👉2021年C#+HALCON实现模板匹配👈


👉C#集成Halcon的深度学习软件👈


👉C#集成Halcon的深度学习软件,带[MNIST例子]数据集👈


👉C#支持等比例缩放拖动的halcon WPF开源窗体控件👈


👉2021年Labview联合HALCON👈


👉2021年Labview联合Visionpro👈


👉基于Halcon及VS的动车组制动闸片厚度自动识别模块👈


✨有关机器视觉、深度学习实战欢迎各位查看个人主页✨


🌟Java、数据库教程与项目🌟


学习Java、数据库教程不再是难问题


🍏《JAVA入门到高级教程》🍏


🍏《数据库入门到高级教程》🍏


有关Java、数据库项目实战


👉Java经典怀旧小霸王网页游戏机源码增强版👈


👉js+css类似网页版网易音乐源码👈


👉Java物业管理系统+小程序源码👈


👉JavaWeb家居电子商城👈


👉JAVA酒店客房预定管理系统的设计与实现SQLserver👈


👉JAVA图书管理系统的研究与开发MYSQL👈


✨有关Java、数据库教程与项目实战欢迎各位查看个人主页✨


🌟分享Python知识讲解、分享🌟


学习Python不再是难问题


🥝《Python知识、项目专栏》🥝


🥝《Python 检测抖音关注账号是否封号程》🥝


🥝《手把手教你Python+Qt5安装与使用》🥝


🥝《用一万字给小白全面讲解python编程基础问答》🥝


🥝《Python 绘制Android CPU和内存增长曲线》🥝


有关Python项目实战


👉Python基于Django图书管理系统👈


👉Python管理系统👈


👉2021年9个常用的python爬虫源码👈


👉python二维码生成器👈


✨有关Python教程与项目实战欢迎各位查看个人主页✨


🌟分享各大公司面试题、面试流程🌟


面试成功不是难事


🍏《2021年金九银十最新的VUE面试题☀️《❤️记得收藏❤️》》🍏


🍏《只要你认真看完一万字☀️Linux操作系统基础知识☀️分分钟钟都吊打面试官《❤️记得收藏❤️》》🍏


🍏《❤️用一万字给小白全面讲解python编程基础问答❤️《😀记得收藏不然看着看着就不见了😀》》🍏


✨有关各大公司面试题、面试流程欢迎各位查看个人主页✨


58084b783cf448a1be3a2feebbab9b5b.gif



相关文章
|
1天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
1天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
2天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
12 3
|
2天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
19 2
|
10天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
40 6
|
18天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
18天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
42 3
|
19天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
23天前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
41 4
|
23天前
|
算法 调度 开发者
多线程编程核心:上下文切换深度解析
在多线程编程中,上下文切换是一个至关重要的概念,它直接影响到程序的性能和响应速度。本文将深入探讨上下文切换的含义、原因、影响以及如何优化,帮助你在工作和学习中更好地理解和应用多线程技术。
33 4

推荐镜像

更多