java多线程(中)

本文深入讲解了多线程编程中的核心概念和技术,包括守护线程、线程加入、线程礼让、线程优先级设置等基础知识,并重点介绍了多线程同步技术的应用,如同步代码块、同步方法等,同时还探讨了线程安全问题及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常用API 2
  • 1、守护线程
    • setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出。该方法必须在启动线程(start)前调用。
  • 2、加入线程

    • join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
    • join(int), 可以等待指定的毫秒之后继续
  • 3、多线程(礼让线程)(了解)

    • yield让出cpu
  • 4、多线程(设置线程的优先级)(了解)

    • setPriority()设置线程的优先级

多线程同步(重点)

多线程(同步代码块)

  • 1.什么情况下需要同步
    • 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.(常用在一个资源多个线程在访问的时候)
    • 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
  • 2.同步代码块

    • 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
    • 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的

      class Printer {
          Demo d = new Demo();
          public static void print1() {
              synchronized(d){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                  System.out.print("a");
                  System.out.print("b");
                  System.out.print("c");
                  System.out.print("d");
                  System.out.print("e");
                  System.out.print("\r\n");
              }
          }
      
          public static void print2() {   
              synchronized(d){    
                  System.out.print("A");
                  System.out.print("B");
                  System.out.print("C");
                  System.out.print("D");
                  System.out.print("\r\n");
              }
          }
      }
      

多线程(同步方法)(掌握)

  • 使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的

    class Printer {
        public static void print1() {
            synchronized(Printer.class){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                System.out.print("A");
                System.out.print("B");
                System.out.print("C");
                System.out.print("D");
                System.out.print("E");
                System.out.print("\r\n");
            }
        }
        /*
         * 非静态同步函数的锁是:this
         * 静态的同步函数的锁是:字节码对象
         */
        public static synchronized void print2() {  
            System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.print("d");
            System.out.print("\r\n");
        }
    }
    

多线程(线程安全问题)

  • 多线程并发操作同一数据时, 就有可能出现线程安全问题
  • 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作

        public class Demo2_Synchronized {
    
            /**
             * @param args
             * 需求:铁路售票,一共100张,通过四个窗口卖完.
             */
            public static void main(String[] args) {
                TicketsSeller t1 = new TicketsSeller();
                TicketsSeller t2 = new TicketsSeller();
                TicketsSeller t3 = new TicketsSeller();
                TicketsSeller t4 = new TicketsSeller();
    
                t1.setName("窗口1");
                t2.setName("窗口2");
                t3.setName("窗口3");
                t4.setName("窗口4");
                t1.start();
                t2.start();
                t3.start();
                t4.start();
            }
    
        }
    
        class TicketsSeller extends Thread {
            private static int tickets = 100;
            static Object obj = new Object();//此处必须是静态的
            public TicketsSeller() {
                super();
    
            }
            public TicketsSeller(String name) {
                super(name);
            }
            public void run() {
                while(true) {
                    synchronized(obj) {
                        if(tickets <= 0) 
                            break;
                        try {
                            Thread.sleep(10);//线程1睡,线程2睡,线程3睡,线程4睡
                        } catch (InterruptedException e) {
    
                            e.printStackTrace();
                        }
                        System.out.println(getName() + "...这是第" + tickets-- + "号票");
                    }
                }
            }
        }
    

多线程(火车站卖票的例子用实现Runnable接口)

其实就是将上面的代码放到run方法中。

多线程(死锁)

  • 多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出现死锁

    • 尽量不要嵌套使用

      private static String s1 = "筷子左";
      private static String s2 = "筷子右";
      public static void main(String[] args) {
          new Thread() {
              public void run() {
                  while(true) {
                      synchronized(s1) {
                          System.out.println(getName() + "...拿到" + s1 + "等待" + s2);
                          synchronized(s2) {
                              System.out.println(getName() + "...拿到" + s2 + "开吃");
                          }
                      }
                  }
              }
          }.start();
      
          new Thread() {
              public void run() {
                  while(true) {
                      synchronized(s2) {
                          System.out.println(getName() + "...拿到" + s2 + "等待" + s1);
                          synchronized(s1) {
                              System.out.println(getName() + "...拿到" + s1 + "开吃");
                          }
                      }
                  }
              }
          }.start();
      }
      

多线程(以前的线程安全的类回顾)

  • A:回顾以前说过的线程安全问题
    • 看源码:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)
    • Vector是线程安全的,ArrayList是线程不安全的
    • StringBuffer是线程安全的,StringBuilder是线程不安全的
    • Hashtable是线程安全的,HashMap是线程不安全的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值