• java(线程初级)


    进程:

    1、进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间,当我们使用微信,又启动了一个进程,操作系统将为微信分配新的内存空间

    2、进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程;有它自身的产生、存在和消亡的过程

    线程:

    1.线程由进程创建的,是进程的一个实体

    2.一个进程可以拥有多个线程

    单线程:同一时刻,只允许执行一个线程

    多线程:同一个时刻,可以执行多个线程

    并发:同一时刻,多个任务交替执行,造成一种“貌似同时”的错觉。简单的说,单核cpu实现的多任务就是并发

    并行:同一时刻,多个任务同时执行。多核cpu可以实现并行

    1. /*
    2. 1.当一个类继承了Thread类,该类就可以当作线程使用
    3. 2.重写run方法,写上自己的业务逻辑
    4. 3.实现了Runnable接口的run方法
    5. 4.当main线程启动一个子线程Thread-0,主线程不会阻塞,会继续执行
    6. 5.此时主线程和子线程交替执行
    7. */
    8. //继承Thread类
    9. class Cat extends Thread{
    10. @Override
    11. public void run() {//重写run方法,完成自己的业务逻辑
    12. int times = 0;
    13. while (true) {
    14. System.out.println("喵喵~"+(times++)+Thread.currentThread());
    15. //让该线程休眠1秒
    16. try {
    17. Thread.sleep(1000);
    18. } catch (InterruptedException e) {
    19. e.printStackTrace();
    20. }
    21. if (times == 80){
    22. break;//退出while循环,线程结束
    23. }
    24. }
    25. }
    26. }
    27. //实现Runnable接口
    28. class A implements Runnable{
    29. int count=0;
    30. @Override
    31. public void run() {
    32. while (true) {
    33. System.out.println("hi"+(count++));
    34. try {
    35. Thread.sleep(1000);
    36. } catch (InterruptedException e) {
    37. e.printStackTrace();
    38. }
    39. if (count == 10)
    40. break;
    41. }
    42. }
    43. }

    线程终止:

    1、当线程完成任务后,会自动退出

    2、还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式

    线程常用方法:

    一、

    1.setName:设置线程名称,使之与参数name相同

    2.getName:返回该线程的名称

    3.start:启动新的线程,使该线程开始执行(底层调用该线程的start0方法)

    4.run:调用线程对象run方法(只是简单的方法调用,不会启动新的线程)

    5.setPriority:更改线程的优先级

    6.getPriority:获取线程的优先级

    7.sleep:在指定的毫秒数内让当前正在执行的线程休眠

    8.interrupt:中断线程(并没有真正的结束线程,一般用于中断正在休眠的线程)

    二、

    1、yield:线程的礼让。让出cpu,让其它线程执行,但礼让时间不确定,所以也不一定礼让成功

    2、join:线程的插队。插队的线程一旦成功,则肯定先执行完插入的线程所有的任务

    1. public class Study {
    2. @SuppressWarnings({"all"})
    3. public static void main(String[] args) throws InterruptedException {
    4. Thread thread = new Thread(new Runnable() {
    5. @Override
    6. public void run() {
    7. int count = 0;
    8. while (true){
    9. System.out.println("子线程:"+"hello"+(++count));
    10. try {
    11. Thread.sleep(1000);
    12. } catch (InterruptedException e) {
    13. e.printStackTrace();
    14. }
    15. if (count == 20)
    16. break;
    17. }
    18. }
    19. });
    20. thread.start();
    21. for (int i = 0; i < 20; i++) {
    22. System.out.println("主线程:"+i);
    23. Thread.sleep(1000);
    24. if (i == 4){
    25. System.out.println("子线程插队");
    26. thread.join();
    27. }
    28. }
    29. }
    30. }

    用户线程和守护线程:

    1、用户线程:也叫工作线程,当线程的任务执行完成或通知方式结束

    2、守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束

    3、常见的守护线程:垃圾回收机制

    怎么将用户线程设置为守护线程:再调用start方法前,先调用setDaemon方法

    线程的七大状态:

    NEW:尚未启动的线程处于此状态

    RUNNABLE:在java虚拟机中执行的线程处于此状态(细分为Ready和Running两个状态)

    BLOCKED:被阻塞等待监控器锁定的线程处于此状态

    WAITING:正在等待另一个线程执行特定动作的线程处于此状态

    TIME_WAITING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态

    TERMINATED:已经退出的线程处于此状态

     线程同步机制:

    1、在多线程编程中,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,在保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性

    2、也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其它线程都不可以对这个内存地址进行操作,直到该线程完成操作,其它线程才能对该内存地址进行操作

    同步具体方法:

    1.同步代码块

    synchronized(对象){ //得到对象的锁,才能操作同步代码

            //需要被同步代码;  }

    2.synchronized还可以放在方法中声明,表示整个方法为同步方法

            public  synchronized  void  m(String  name){

                         //需要被同步的代码;  }

    互斥锁:

    1.java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性

    2.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象

    3.关键字synchronized来与对象的互斥锁联系,当某个对象用synchronized修饰,表明该对象在任一时刻只能由一个线程访问

    4.同步的局限性:导致程序的执行效率要降低

    5.同步方法(非静态的)的锁可以是this,也可以是其它对象(要求是同一个对象

    6.同步方法(静态的)的锁为当前类本身

    线程的死锁:

    概念:多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程中一定要避免死锁的发生

    1. class DeadLockDemo extends Thread{
    2. private static Object o1 = new Object();
    3. private static Object o2 = new Object();
    4. boolean flag;
    5. public DeadLockDemo(boolean flag){
    6. this.flag=flag;
    7. }
    8. @Override
    9. public void run() {
    10. /*
    11. 1.如果flag为T,线程A就会先得到/持有o1对象锁,然后尝试去获取o2对象锁
    12. 2.如果线程A得不到o2对象锁,就会Blocked
    13. 3.如果flag为F,线程B就会先得到/持有o2对象锁,然后尝试去获取o1对象锁
    14. 4.如果线程B得不到o1对象锁,就会Blocked
    15. */
    16. if (flag){
    17. synchronized (o1){
    18. System.out.println(Thread.currentThread().getName()+"进入1");
    19. synchronized (o2){
    20. System.out.println(Thread.currentThread().getName()+"进入2");
    21. }
    22. }
    23. }else{
    24. synchronized (o2){
    25. System.out.println(Thread.currentThread().getName()+"进入3");
    26. synchronized (o1){
    27. System.out.println(Thread.currentThread().getName()+"进入4");
    28. }
    29. }
    30. }
    31. }
    32. }

    释放锁:

    1、当前线程的同步方法、同步代码块执行结束

    2、当前线程在同步代码块、同步方法中遇到break、return

    3、当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束

    4、当前线程在同步代码块,同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁

    下面操作不会释放锁:

    1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁

    2.线程执行同步代码块时,其它线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁

  • 相关阅读:
    项目管理-2023西电网课课后习题答案-第三章
    2022-8-30 第七小组 学习日记 (day54)JavaWeb、Servlet、HTTP-请求 响应、乱码问题
    Spring注解开发-依赖注入@Autowired扩展
    postgresql源码学习(40)—— 崩溃恢复② - 恢复起点
    使用 ErrorStack 在出现报错 ORA-14402 时产生的日志量
    Linux常用命令
    详解FreeRTOS:FreeRTOS任务调度器开启过程源码分析(进阶篇—5)
    使用 OpenCV 进行图像投影变换
    【Redis】
    pycharm连接服务器
  • 原文地址:https://blog.csdn.net/weixin_63954483/article/details/125578459