线程状态及创建线程的方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/John_z1/article/details/88839392

目录

一、线程状态

二、创建线程的方式

2.1 继承Thread类

2.2 实现Runnable接口

三、wait()、sleep()、notify()和yield()等方法介绍


 


一、线程状态

为了方便理解,线程运行状态大致可分为:初始状态、就绪状态、运行状态、阻塞状态、睡眠状态、等待状态和消亡状态。

1.当一个线程被创建的时候处于初始状态

2.线程对象创建后,其他线程(如main线程)调用start()方法,该线程处于就绪状态。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU执行权。就绪状态的线程在获的CPU时间片后变成运行状态

3.线程进入synchronized关键字修饰的方法或者代码块的状态(获得锁)为阻塞状态。处于该状态的线程具备运行资格,但没有执行权

4.当线程调用sleep(time)方法变成睡眠状态,即放弃了执行资格,在达到一定时间time后会被自动唤醒变成阻塞状态等待CPU执行。

5.当线程调用wait()方法变成等待状态,即放弃了执行资格,只有当调用notify()显示唤醒,才会使其处于一个阻塞状态等待CPU执行,否则将无限期的等待。

6.当线程调用stop()方法或者run()方法执行完毕,线程变成消亡状态。线程一旦终止了,无法复生。如果在终止的线程中调用start(),会抛出java.lang.IllegalThreadStateException异常。

二、创建线程的方式

创建线程的方式有两种,分别是继承Thread类实现Runnable接口

2.1 继承Thread类

继承Thread类,覆盖run()方法。

public class Ticket extends Thread {

    private int tick = 100;

    @Override
    public void run() {
        while (true) {
            if (tick > 0) {
                System.out.println(Thread.currentThread().getName()+" sale ticket: " + (tick--));
            }
        }
    }
}
        // 创建线程对象
        Ticket t1= new Ticket();
     
        //调用start()方法
        t1.start();
        

2.2 实现Runnable接口

步骤:

  1. 定义类实现Runnable接口;
  2. 覆盖Runnable中的run()方法;
  3. 通过Thread类建立线程对象;
  4. 将Runnable接口中的子类对象作为参数传递给Thread类的构造函数。(自定义run()方法所属的对象是Runnable接口子类对象,需要让线程去指定对象的run()方法,就必须明确该run()方法的所属对象)
  5. 调用Thread类的start()方法开启线程并调用Runnable接口的run()方法。
public class TicketRunnable implements Runnable {

    // 问题:当多条语句在操作同一个线程共享数据的时候,一个线程对多个语句只执行了一部分,还没有执行完, 另一个程序就参与了进来执行,导致共享数据错误。
    // 解决方案:对多条语句操作共享数据时,只能让一个线程都执行完,在执行过程中,其他线程不能执行 同步代码块synchronized
    private int tick = 100;

    @Override
    public void run() {
        while (true) {
           
            synchronized (new Object()){
                if (tick > 0) {
                    try{
                        Thread.sleep(30);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" sale ticket: " + (tick--));
                }

            }

        }
    }
}
        TicketRunnable ticketRunnable = new TicketRunnable();
        Thread thread= new Thread(ticketRunnable);
        Thread thread2= new Thread(ticketRunnable);
        thread.start();
        thread2.start();

三、wait()、sleep()、notify()和yield()等方法介绍

wait()、notify()和notifyAll()属于对象,而sleep()和yield()属于Thread类。

wait()、notify()和notifyAll()必须放在同步代码块中执行,wait()是线程从运行状态变成阻塞状态并且释放同步锁,只有当调用notify()或者notifyAll()唤醒一个正在等待该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronize修饰的代码块)后再释放锁。

sleep()使线程从运行状态变成阻塞状态不会释放锁,等待休眠时间到,线程重新被唤醒,由阻塞状态变成就绪状态

yield()使当前线程从运行状态变成就绪状态不会释放锁,让其他同等优先级的线程获得执行权。

猜你喜欢

转载自blog.csdn.net/John_z1/article/details/88839392