线程的创建方式、安全、状态

多线程

今天我们来聊聊多多线程

  1. 多线程创建方式
  • 通过继承Thread
  • 创建通过接口Runnable创建
  1. 线程安全
  • 同步代码块
  • 同步方法
  • Lock锁
  1. 线程状态

Thread与Runnable 创建

Thread

public class MyThread extends Thread {
 
  public MyThread(String name){
    super(name);
  }

  public void run(){
    for (int i = 0; i < 20; i++) {
      //getName()方法 来自父亲
      System.out.println(getName()+i);
    }
  }
}

// 测试类 
public class Demo {
  public static void main(String[] args) {
    System.out.println("这里是main线程");
    MyThread mt = new MyThread("TR");
    mt.start();//开启了一个新的线程
    for (int i = 0; i < 20; i++) {
        System.out.println("MI:"+i);
    }
  }
}

Runnable

public class MyRunnale implements Runnable{
  @Override
  public void run(){
    for(int i = 0 ; i < 20 ; i++){
      System.out.println(Thread.cerrentThread().getName() + i);

    }
  }
}

// 测试类2 
public class Demo02{
  public static void mian(Stirng []args){
  // 创建自定义类对象 线程任务对象 
  MyRunnable mr = new MyRunnable();
  // 创建线程对象
  Thread t = new Thread(mr,"Run对象");
  t.start();
  
  System.out.println("main的线程");

  }
}

Thread和Runnable区别:
如果一个类继承Thread,他就不适合资源共享,但是使用Runnable接口的话,则更容易实现资源共享.

  1. 使用多个相同代码共享一个资源
  2. 可以避免java中单继承的局限性
  3. 线程池中只能放入Runnable或Callble类线程,不能直接放继承了Thread的类

线程安全

同步代码块: synchronized关键字 表示用于某个方法中的某个区块,实行互斥访问

public class Ticket{

 private int  ticket = 100;
 Object lock = new Objcet();

// 同步代码块
    @Override
    public void run(){
        // 买票口永久开启
        while(true){
            synchronized(lock){
                if (ticket > 0 ){ // 有票
                    try{
                        Thread.sleep(50);
                    } catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    String name  = Thread.currentThread().getName();
                    System.out.println(  name + "正在买" + ticket-- );
                }
            }
        }
    }
}

同步方法: 使用synchronzied修饰的方法,就是同步方法,保证A线程执行别的线程等着。

public class Ticket implements Runnable{
  private int ticket = 100;
  /*
  * 执行卖票操作
  */
  @Override
  public void run() {
    //每个窗口卖票的操作
    //窗口 永远开启
    while(true){
        sellTicket();
    }
  }
  /*
  * 锁对象 是 谁调用这个方法 就是谁
  * 隐含 锁对象 就是 this
  */
  //同步方法
  public synchronized void sellTicket(){
    if(ticket>0){//有票 可以卖
    //出票操作
    //使用sleep模拟一下出票时间
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
      
      e.printStackTrace();
    }
    //获取当前线程对象的名字
    String name = Thread.currentThread().getName();
    System.out.println(name+"正在卖:"+ticket‐‐);
    }
  }
}

Lock锁
Lock锁也被称为同步锁.方法如下:
lock:加同步锁。
unlock: 释放同步锁。

public class Ticket implements Runnable{
  private int ticket = 100;
  Lock lock = new ReentrantLock();
  /*
  * 执行卖票操作
  */
  @Override
  public void run() {
    //窗口 永远开启
    while(true){
      lock.lock(); // 加同步锁 
      if(ticket>0){//有票 可以卖
        //出票操作
        //使用sleep模拟一下出票时间
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
         
          e.printStackTrace();
        }
        //获取当前线程对象的名字
        String name = Thread.currentThread().getName();
        System.out.println(name+"正在卖:"+ticket‐‐);
      }
      lock.unlock(); // 释放同步锁 
    }
  }
}

线程状态

 /*
        *   线程状态
        *
        *  new 新建
        *  Runnable 可运行{
        *  线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,
        *  这取决于操作系统处理器。
        *  }
        *  Blocked 锁阻赛 {
        *  一个线程想要获得一个对象锁,而对象锁正在被别一个线程所持有,线程就进入了Blocked
        *  当线程拥有对象锁,就变成 Runnable
        *  }
        *   Waiting 无线等待 {
        *   一个线程等待别一个线程(唤醒) 此线程就进入无线等待的状态 必须要别一个线程唤醒
        *
        *  }
        *  TimedWaiting 计时等待 {
        *   同是 Waiting状态, 但他有几个方法有超时参数,当你调用它们就进入TimedWaiting状态
        *   这个状态会有唤醒通知
        *  }
        *  Teminated()被终止 {
        *   因为run方法正常退出而死亡
        * }
        *
        * */

你可能感兴趣的:(线程)