多线程创建方式、状态、和安全

一、多线程

多任务多条路径多个顺序同时执行就是多线程。

线程的优点和缺点

优点:

  • 资源利用率更好

  • 程序设计在某些情况下更简单

  • 程序响应更快

  • 提高效率,同时执行

缺点:

  • 设计复杂

  • 上下文切换开销大

1.线程的创建

1)继承Thread类,重写run()方法,run方法中定义多线程的线程体。

创建 Thread 子类的一个实例并重写 run 方法,run 方法会在调用 start()方法之后被执 行,示例如下:

package com.thread01;
//多线程:多任务多条路径多条顺序流同时执行
public class TextThread1 extends Thread{//继承Thread类
    @Override
    public void run() {//重写run方法
        for(int i=0;i<100;i++) {
            System.out.println("睡觉");
            try {
                //设置睡眠时间
                Thread.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    public static void main(String[] args) {
        //创建多线程
        TextThread1 t=new TextThread1();
        //开始线程
        t.start();
        for(int i=0;i<100;i++) {
            System.out.println("熬夜");
            try {
                //设置睡眠时间
                Thread.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
}
​

2)实现Runnable接口,重写run()方法

推荐使用的优点:1.避免单继承的局限性 2.实现资源共享。

package com.thread01;
/**
 *  实现Runnable接口,重写run()方法
 *      推荐:
 *          1.避免单继承的局限性
 *          2.实现资源共享
 * 
 * */
public class TextThread2 implements Runnable{//实现Runnable接口
​
    @Override
    public void run() {//重写run方法
        for(int i=0;i<20;i++) {
            System.out.println("黑眼圈");
            try {
                //设置睡眠时间
                Thread.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
    public static void main(String[] args) {
        //创建多线程
        Thread t=new Thread(new TextThread2());//因为实现接口通过子类实现
        //开启线程
        t.start();
        for(int i=0;i<20;i++) {
            System.out.println("贼精神");
            try {
                //设置睡眠时间
                Thread.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
    
}
​

3)实现Callable接口,重写call方法

2.线程的状态

1)五种状态

  • 新生状态:new创建一个线程的时候

  • 就绪状态:start(),线程会进入就绪队列,等待cpu的调度

  • 运行状态:cpu调用分配时间片给线程,线程就会运行

  • 阻塞状态:sleep(),一个线程一旦就如到阻塞状态,阻塞解除之后,不会马上恢复到运行,会恢复到就绪状态,再次等待cpu的调度

  • 终止状态:线程结束了, 一个线程一旦进入终止状态,再也不会恢复

2)进入就绪状态的方式

  • start()

  • 阻塞解除

  • 线程切换,被切换的线程会恢复就绪状态

  • yield() :让出cpu的资源,恢复到就绪状态

3)进入阻塞状态的方式

  • sleep:线程睡眠

    • 模拟网络延迟

    • 放大问题的可能性

  • wait

  • join:插队线程,把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

4)控制线程终止的方式

  • stop不推荐

  • 正常执行结束

  • 通过表示判断

5)线程优先级

优点:提高先执行的概率

  • getPriority() 返回该线程的优先级。

  • setPriority(int newPriority)改变这个线程的优先级。

  • 优先级大小为1~10 ,1最小 , 10最大 , 默认是5。

3.线程安全

多线程同时操作同一份资源才有可能会出现线程不安全的问题,需要控制安全

1)同步锁: synchronized

2)同步方法

  • 在方法上使用synchronized修饰

  • 成员方法,相当于锁this,代码范围为方法

  • 静态方法,相当于锁类(类的class对象),代码范围为方法

3)同步块

  • synchronized(锁的内容){同步的代码范围}

  • 锁的内容: this 类.class 资源(成员变量)

    • 类.class 相当于把这个类,类的所有内容锁住了,类的所有对象都锁住

      package com.thred02;
      //多线程
      /**
       * 简单模拟12306例子
       *  100张票,想要让3个人同时买完这100张票
       *  资源共享:共享资源100张票
       * */
      public class TextThread03 implements Runnable{
          int num=100;
          
          public static void main(String[] args) {
              TextThread03 t=new TextThread03();
              Thread t1=new Thread(t,"美人师兄");
              Thread t2=new Thread(t,"东方不败");
              Thread t3=new Thread(t,"齐天大圣");
              t1.start();
              t2.start();
              t3.start();
              
          }
      ​
          @Override
          public void run() {
              while(true) {
                  synchronized (TextThread03.class) {//ThreadDemo02.class类的class对象()
                      if(num<=0) {
                          break;
                      }
                      try {
                          Thread.sleep(100);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()+"正在购买第"+num--+"张票");
                  }
                  
              }
              
          }
          
      }
      ​

       

    • this 当前调用成员方法的对象,相当于把这个对象的所有资源都锁住了,可以只锁资源

      public class TextThread4 implements Runnable{
          int num=100;
          
          public static void main(String[] args) {
              TextThread4 t=new TextThread4();
              Thread t1=new Thread(t,"美人师兄");
              Thread t2=new Thread(t,"东方不败");
              Thread t3=new Thread(t,"齐天大圣");
              t1.start();
              t2.start();
              t3.start();
              
          }
          
          
          @Override
          public void run() {
              while(true) {
                  if(!get()) {
                      break;
                  }
              }
              
          }
      ​
          public boolean get() {
              synchronized (this) {//this 当前调用成员方法的对象
                  if(num<=0) {
                      return false;
                  }
                  try {
                      Thread.sleep(4);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println(Thread.currentThread().getName()+"正在购买第"+num--+"张票");
              }
              
              return true;
          }
      }
      ​

       

    • 资源: 成员变量,一定要是自定义的引用数据类型的对象

      public class TextThread2 implements Runnable{
          //int num=100;
          User u=new User();
          public static void main(String[] args) {
              TextThread2 t=new TextThread2();
              Thread t1=new Thread(t,"美人师兄");
              Thread t2=new Thread(t,"东方不败");
              Thread t3=new Thread(t,"齐天大圣");
              t1.start();
              t2.start();
              t3.start();
              
          }
          @Override
          public void run() {
              while(true) {
                  synchronized (u) {//成员变量:自定义引用类型
                      if(u.n<=0) {
                          break;
                      }
                      try {
                          Thread.sleep(4);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(Thread.currentThread().getName()+"正在购买第"+u.n--+"张票");
                  }
                  
              }
              
          }
      ​
      }
      //自定义引用类型
      class User{
          int n=100;
      }

       

  • 锁的范围:{}->中代码的范围

4) 注意

  • 锁的范围太大,效率低

  • 锁的范围太小,锁不住

  • 锁不变的内容

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值