1,线程有哪些状态?

  • 创建
  • 就绪
  • 阻塞
  • 运行
  • 死亡
    image.png

2,各状态过程详情

1. 创建

当创建了一个线程对象的时候,就进入了该状态:
Thread t = new Thread( );

2. 就绪

当调用了start( )方法的时候,线程立即进入就绪状态,但是,这不意味着立即被调度执行,所以,此时等待CPU的调度。

3. 运行

当CPU调度执行的时候,进入该状态,线程才开始真正执行线程体里面的代码块,但是,有时候并不会一直等该线程执行完。

4. 阻塞

所以,当调用sleep( ),wait( )或者同步锁定时,线程就进入了阻塞的状态,意味着代码不往下执行了,阻塞事件解除之后,重新进入就绪状态,再次等待CPU的调度。

5. 死亡

线程中断或者结束,一旦进入死亡状态,就不能再次运行。

3,线程的创建

可见文章:线程创建的方式

4,线程的停止

  • 我们不建议使用stop( )方法,或者destroy( )方法,这些方法已经被废弃,官方不建议使用
  • 推荐线程自己停止
  • 推荐使用标志位来进行线程的停止,如:flag == false,则线程终止。 具体实现如下:
public class TestCreate implements Runnable {
    private boolean flag = true;

    @Override
    public void run() {
        int count = 0;
        while (flag) {
            System.out.println("run...... " + count++);
        }
    }

    public void myStop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        TestCreate testCreate = new TestCreate();
        new Thread(testCreate).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main thread!" + i);
            if (i == 900) {
                testCreate.myStop();
                System.out.println("thread stop!");
            }
        }
    }
}

5,线程休眠

image.png

  • sleep(时间)指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后,线程进入的是就绪状态
  • sleep可以模拟网络延时,倒计时等
  • 每一个对象都有一个锁,sleep不会释放锁
5.1 使用sleep模拟倒计时
public class TestSleep {
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while (true) {
            Thread.sleep(1000);
            System.out.println(num--);
            if (num <= 0) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
5.2 使用sleep模拟网络延迟,可以将问题的发生性放大,可快速可见问题所在
public class TestSleepYanchi implements Runnable {
    private int ticketcount = 10;

    @Override
    public void run() {
        while (true) {
            if (ticketcount <= 0) {
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "get the " + ticketcount-- + " ticket");
        }
    }


    public static void main(String[] args) {
        TestSleepYanchi testSleepYanchi = new TestSleepYanchi();
        new Thread(testSleepYanchi, "Tom").start();
        new Thread(testSleepYanchi, "Jane").start();
        new Thread(testSleepYanchi, "Kangkang").start();
    }
}

6,线程礼让

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转换为就绪状态
  • 让CPU重新调度,所以,礼让不一定成功,看CPU的心情 实现如下:
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield, "A").start();
        new Thread(myYield, "B").start();
    }
}

class MyYield implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " thread start");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + " thread end");
    }
}

礼让成功:image.png

礼让失败:image.png

7,合并线程join

  • 待此线程执行完成之后,再执行其他的线程,其他的线程处于阻塞状态
  • 可以想象成插队,想象成为一个VIP线程
  • 这个VIP线程可以是新来的,可以是之前就在执行的
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("i am VIP....." + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        //main thread
        for (int i = 0; i < 1000; i++) {
            System.out.println("main thread " + i);
            if (i == 200) {
                thread.join();//vip is came.....
            }
        }
    }
}