并发编程之创建线程和线程的状态

创建线程的三种方式

1.继承Thread类 重写run方法

class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":打了" + i + "个小兵");
        }
    }
}
public class Test {
    public static void main(String[] args) {
        //创建MyThread对象
        MyThread t1=new  MyThread();
        MyThread t2=new  MyThread();
        MyThread t3=new  MyThread();
        //设置线程的名字
        t1.setName("鲁班");
        t2.setName("刘备");
        t3.setName("亚瑟");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

2.实现eunnable 重写run方法

 class MyRunnable implements Runnable {

    public void run() {
        for (int i = 0; i < 10; i++) {
            try {//sleep会发生异常要显示处理
                Thread.sleep(20);//暂停20毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "打了:" + i + "个小兵");
        }
    }
}

public class Test {
    public static void main(String[] args) {

        //创建MyRunnable类
        MyRunnable mr = new MyRunnable();
        //创建Thread类的有参构造,并设置线程名
        Thread t1 = new Thread(mr, "张飞");
        Thread t2 = new Thread(mr, "貂蝉");
        Thread t3 = new Thread(mr, "吕布");
        //启动线程
        t1.start();
        t2.start();
        t3.start();

  
    }
}
class CallerTask implements Callable {
    public String call() throws Exception {
        return "Hello,i am running!";
    }

    public static void main(String[] args) {
        //创建异步任务
        FutureTask task=new FutureTask(new CallerTask());
        //启动线程
        new Thread(task).start();
        try {
            //等待执行完成,并获取返回结果
            String result=task.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

注意!!:以上两种方式都是要调用start方法,才能真正实现多线程。直接调用run相当于调用普通方法

线程状态

// Thread.State 源码
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

NEW状态

表示线程已经被创建,但是还未被启动

测试在start之前调用getState查看状态,是NEW

  Thread t1 = new Thread(mr, "张飞");
        Thread t2 = new Thread(mr, "貂蝉");
        Thread t3 = new Thread(mr, "吕布");
        System.out.println(t1.getState());

        //启动线程
        t1.run();

Runnable状态

表示当前线程正在运行中。处于 RUNNABLE 状态的线程在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源。

在操作系统层面,线程状态包括ready和running,但是在JVM层面,只能看到Runnable状态,也就是将这两种状态统称为Runnable(运行中)。

Runnable状态可以由NEW状态调用start方法转变过来,但是:

  1. 反复调用同一个线程的 start 方法不可行,回抛出异常
  2. 假如一个线程执行完毕(此时处于 TERMINATED 状态),再次调用这个线程的 start 方法也不可行

看下面的start代码,每次进入会判断threadStatus变量,这个变量代表当前线程的状态。如果线程已经启动或者已经终止,threadStatus就不等于0,进入start就会 throw  IllegalThreadStateException();

// 使用synchronized关键字保证这个方法是线程安全的
public synchronized void start() {
    // threadStatus != 0 表示这个线程已经被启动过或已经结束了
    // 如果试图再次启动这个线程,就会抛出IllegalThreadStateException异常
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    // 将这个线程添加到当前线程的线程组中
    group.add(this);

    // 声明一个变量,用于记录线程是否启动成功
    boolean started = false;
    try {
        // 使用native方法启动这个线程
        start0();
        // 如果没有抛出异常,那么started被设为true,表示线程启动成功
        started = true;
    } finally {
        // 在finally语句块中,无论try语句块中的代码是否抛出异常,都会执行
        try {
            // 如果线程没有启动成功,就从线程组中移除这个线程
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            // 如果在移除线程的过程中发生了异常,我们选择忽略这个异常
        }
    }
}

BLOCK

阻塞状态。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区。

WAITING

等待状态。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒。

BLOCK和WAITING有哈区别?

TIMED_WAITING

TIMED_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将线程置于 TIMED_WAITING 状态。当超时时间结束后,线程将会返回到 RUNNABLE 状态。

线程状态的转变

并发编程之创建线程和线程的状态_第1张图片

 

你可能感兴趣的:(java,java,开发语言)