Java小白进阶笔记(7)-多线程

简介: 线程与进程是包含关系。一个进程至少包含一个线程,至多可以包含n个线程,一个线程必须从属于一个进程。

Java的多线程基础学完了!
还是看的偏头痛杨大哥的博客:
10.偏头痛杨的Java入门教学系列之初级多线程篇

记一下学习笔记,最后是偏头痛杨留下的作业,我的一种解答。

线程与进程

线程与进程是包含关系。一个进程至少包含一个线程,至多可以包含n个线程,一个线程必须从属于一个进程。

线程(Thread)

  • 单线程是一条逻辑执行流,从上到下执行,遇到阻塞就会停止。
  • 多线程是以资源(内存,CPU)换时间,如果服务端的内存和CPU使用率低,那使用多线程可以提高效率。
  • 线程是进程的基本单位
  • 当进程被初始化后,主线程就被创建了。
  • 线程可以拥有自己的堆栈、计数器、局部变量,但不用有系统资源,同一进程下的多个线程共享该进程所拥有的全部资源
  • 线程的执行是抢占式的,相同进程下的多个线程可以并发执行并相互通信方便,线程之间共享内存。
  • 多线程的使用有效提高了CPU的利用率从而提升了运行效率。

进程(Process)

  • 进程是操作系统中独立存在的实体拥有独立的系统资源(内存,私有地址空间)
  • 在没有允许的情况下,两个进程不可以直接通讯。
  • 进程之间不共享内存,通信较困难。
  • 进程是程序的一种动态形式,是cpu,内存等资源占用的基本单位,而线程不能独立的占有这些资源。

线程的概念

线程的创建与启动

  • 有三种方式创建&&启动线程:Runnable,Callable,Thread
  • 在执行main()的时候,main()本身会启动一个main线程,也叫主线程,这与我们自己新建的线程不同(如没有run()方法)。

线程的状态和生命周期

  • 在JDK1.5之后Thread类有6种状态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED.

线程的控制

join加入

  • “插队”,在Thread类种提供了join()方法来实现。当在某个线程中(如在某个线程的run()方法中或者main的方法体中)调用其他线程的join()方法时,调用的线程将被阻塞,直到被join()方法加入的线程执行完之后它才会继续执行。
  • 我们可以将大问题分解程许多个小问题,再为每个小问题分配一个线程,当所有的小问题都完成之后,再调用主线程接着往下走。

sleep休眠

  • Thread.sleep()让执行的线程暂停若干毫秒,进入等待状态,时间到了自动恢复。
  • 在休眠时间范围内即使当前没有任何可执行线程,休眠中的线程也不会被执行。
  • sleep()不释放对象锁,如果当前线程持有synchronized锁并sleep(),则其他线程仍不能访问。

yield让步

  • Thread.yield()使当前线程放弃CPU调度,但不是使线程阻塞&等待,线程仍处于可执行状态,随时可能再次获得CPU调度。
  • 相当于当前线程已经执行了足够的时间从而转到另一个线程。
  • 也有可能出现刚调用完Thread.yield()放弃CPU调度,当前线程立刻又获得CPU调度

Priority优先级

  • 优先级高的具有较多的执行机会,优先级低的线程具有较少的执行机会。这只是概率的大小,并不严格的先后执行
  • 每个线程的默认优先级与创建它的父线程的优先级相同。优先级范围:1-10。
  • 一般用Thread.MAX_PRIORITY等。

daemon后台&守护线程

  • 后台线程是指在后台运行的线程,为其他线程提供服务,比如JVM的GC。
  • 如果前台线程全部死亡,那后台线程自动死亡。
  • 前台线程创建的子线程默认为前台线程,后台线程创建的子线程默认为后台线程。
  • 把某线程设置为后台线程的操作必须在线程启动之前,否则会报错。

线程的同步

线程安全问题

  • 由多个线程同时处理共享资源所导致的
  • 比如买票卖出-1张的情况

同步代码块

  • 为了解决线程安全问题,Java提供了同步机制,当多个线程使用同一种共享资源时,可以将处理的共享资源的代码放在synchronized代码块中,这个代码块就是同步代码块
  • 同步代码块的锁对象可以是任意类型的对象,但多个线程共享的锁对象必须是唯一的。
  • 锁对象的创建不能放到run()方法中,否则每次都会产生新的对象,每个线程都有一个不同的锁,不能达到同步效果。
  • synchronized锁和Lock锁:详细看偏头痛杨原文。

线程的通信

线程组&&线程池

略(以后学明白了再补充)

作业

使用3个线程,要求三个线程顺序执行,不允许使用sleep()强制让线程有顺序。
线程A输出1、2、3,
线程B输出4、5、6,
线程C输出7、8、9,
线程A输出10、11、12,
线程B输出13、14、15,
以此类推,一直输出到1000为止。

我的解答

package thread_package;

public class ThreadHomeWork2 {
    public static void main(String [] args) {
        Num num = new Num();
        SynchronizedThread r = new SynchronizedThread(num);
        
        
        while(num.cnt<20) {
            new Thread(r).start();
            new Thread(r).start();
            new Thread(r).start();
            
        }
    }
}

class Num{
    String flag = "A";
    int cnt = 1;
}


class SynchronizedThread implements Runnable{
    Num num;
    public SynchronizedThread(Num num) {
        this.num = num;
    }
    public void run() {
        synchronized(num) {
            for(int i=0;i<3;i++) {
                if(num.cnt <=20) {
                    System.out.println("线程:"+num.flag+" "+num.cnt++);
                }
                else {
                    break;
                }
            }
            if("A".equals(num.flag)) {
                num.flag = "B";
            }
            else if("B".equals(num.flag)) {
                num.flag = "C";
            }
            else {
                num.flag = "A";
            }
        }
    }
}

目录
相关文章
|
16天前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
142 60
【Java并发】【线程池】带你从0-1入门线程池
|
5天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
55 23
|
12天前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
81 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
1月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
106 14
|
1月前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
57 13
|
2月前
|
存储 Java 开发者
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
本文详细介绍了 Java 中 `toString()` 方法的重写技巧及其重要
63 10
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
|
1月前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
2月前
|
前端开发 JavaScript Java
Java构建工具-maven的复习笔记【适用于复习】
这篇文档由「潜意识Java」创作,主要介绍Maven的相关知识。内容涵盖Maven的基本概念、作用、项目导入步骤、依赖管理(包括依赖配置、代码示例、总结)、依赖传递、依赖范围以及依赖的生命周期等七个方面。作者擅长前端开发,秉持“得之坦然,失之淡然”的座右铭。期待您的点赞、关注和收藏,这将是作者持续创作的动力! [个人主页](https://blog.csdn.net/weixin_73355603?spm=1000.2115.3001.5343)
48 3
|
2月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
126 17

热门文章

最新文章