java线程创建,线程运行状态,睡眠、等待、唤醒、中断线程

创建线程:

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

public class MyThread extends Thread {
    
    

    @Override
    public void run() {
    
    
        System.out.println("线程=====:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
    
    
        for(int i = 0 ; i < 10 ; i++){
    
    
            MyThread myThread = new MyThread();
            myThread.setName("thread" + i);//设置线程名称
            myThread.start(); //启动线程
        }
        System.out.println("主线程:" + Thread.currentThread().getName());
    }
}

2、实现Runnable接口,重写run()方法,将实现Runnable的对象传入Thread对象

public class MyThreadRunnable implements Runnable {
    
    

    @Override
    public void run() {
    
    
        System.out.println("线程===========:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
    
    
        for(int i = 0;i < 10 ;i ++){
    
    
            MyThreadRunnable myThreadRunnable = new MyThreadRunnable();
            Thread thread = new Thread(myThreadRunnable);
            thread.setName("thread" + i);
            thread.start();
        }
        System.out.println("主线程==:" + Thread.currentThread().getName());
    }
}

3、实现Callable接口(有返回值)

public class MyCallable implements Callable {
    
    

    private String name;

    public MyCallable(String name){
    
    
        this.name = name;
    }

    public Object call() throws Exception {
    
    
        return this.name;
    }

    public static void main(String[] args) throws Exception{
    
    
        for(int i = 0 ; i < 10 ; i++){
    
    
            MyCallable myCallable = new MyCallable("runnable" + i);
            FutureTask<String> task = new FutureTask<String>(myCallable);
            Thread thread = new Thread(task);
            thread.start();
            //调用FutureTask.get()方法会阻塞主线程
            String result = task.get();
            System.out.println(result);
        }
    }
}

线程状态:

新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态: 当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态: 如果就绪状态的线程获取 CPU 资源,就可以执行
run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态: 如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞 状态。
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态: 一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

守护线程: 为用户线程服务的线程(Daemon Thread)。不影响程序运行,守护线程未执行结束,虚拟机也会退出,也就是方法执行完毕。

Thread.setDaemon(true); //设置Daemo为true,则为守护线程。未设置的为用户线程
public class MyThreadRunnable implements Runnable {
    
    

    @Override
    public void run() {
    
    
        try {
    
    
            //守护线程睡眠期间虚拟机退出,守护线程不会影响虚拟机退出,用户线程会,虚拟机会等到所有用户线程执行完毕再退出
            Thread.sleep(5000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("线程===========:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
    
    
        MyThreadRunnable myThreadRunnable = new MyThreadRunnable();
        Thread thread = new Thread(myThreadRunnable);
        thread.setDaemon(true);//设置为守护线程
        thread.start();
        System.out.println("主线程==:" + Thread.currentThread().getName());
    }
}

线程的方法

Thead.sleep(): 线程睡眠,释放cpu资源。如果线程持有锁不会释放线程锁。

public static void main(String[] args) {
    
    
    System.out.println("thread sleep start=====" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
    try {
    
    
        Thread.sleep(2 * 1000); //线程睡2秒
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    System.out.println("thread sleep end=====" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
}

Thread.join() : 调用线程等待被调用线程运行结束后在运行。线程同步。持有线程锁会释放线程锁。

public static void main(String[] args) throws InterruptedException {
    
    
    /**
     * 主线程(main线程)调用线程t的join方法,主线程会等待t线程运行结束再次运行
     */
    Thread t = new Thread(new Runnable() {
    
    
        @Override
        public void run() {
    
    
            try {
    
    
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    });
    t.start();
    //t.join(100); //设置等待时间 等待超时不等待
    t.join();
    System.out.println(Thread.currentThread().getName());
}

Thread.yield() : 线程让步,使线程让出cpu资源,回到就绪状态继续竞争cpu资源。如果线程持有锁不会释放线程锁。

public static void main(String[] args) throws Exception{
    
    
    for(int i = 0;i < 5 ;i ++){
    
    
        Thread t = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                for(int j = 0; j < 10 ;j ++){
    
    
                    System.out.println(Thread.currentThread().getName() + "===" + j);
                    /**
                     * 调用 yield()会使线程让出cpu资源重新从运行状态变为就绪状态(继续获取cpu资源)
                     * 导致输出不是0-9,中间会有其它线程的输出
                     */
                    Thread.yield();
                }
            }
        });
        t.setName("线程" + i);
        t.start();
    }
}

wait() : 线程等待。释放锁。需要唤醒才继续运行,唤醒的线程需要重新获取锁才能运行。
notify()/notifyAll() : 唤醒线程。(唤醒在当前锁中wait的线程)。
notify()/notifyAll()和wait()方法需要在synchronized内部调用,使用锁对象调用。

public class Queue {
    
    

    private static final List<Integer> queueList = new ArrayList<>();

    /**
     * 加入队列
     * @param s
     */
    public synchronized static void addQueue(Integer s){
    
    
        queueList.add(s);
        Queue.class.notifyAll();
    }

    /**
     * 队列中取出
     * @return
     */
    public synchronized static Integer getQueue(){
    
    
        while (queueList.isEmpty()){
    
    
            try {
    
    
                Queue.class.wait();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
        Integer str = queueList.get(0);
        queueList.remove(0);
        return str;
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        //消费
        new Thread(() -> {
    
    
            //读取队列中的数据
            while (true){
    
    
                System.out.println("取出================:" + Queue.getQueue());
            }
        }).start();
        //队列中存入
        for(int i = 0 ;i < 3000 ;i ++){
    
    
            Thread.sleep(1000);
            final int finalI = i;
            Thread t = new Thread(new Runnable() {
    
    
                public void run() {
    
    
                    Queue.addQueue(finalI);
                    System.out.println("插入队列完成:" + finalI);
                }
            });
            System.out.println("准备插入队列:" + finalI);
            t.start();
        }
    }
}

Thread.interrupt() : 中断线程。线程正常运行外部调用interrupt()方法,线程的isInterrupted()会为true,如果线程正在sleep(),则会抛出InterruptedException异常,根据具体业编写中断线程的代码。

public class InterruptThread extends Thread {
    
    
    @Override
    public void run() {
    
    
        //isInterrupted()为false则未被中断
        while (!isInterrupted()){
    
    
            System.out.println("线程:" + getName());
            try {
    
    
                Thread.sleep(10 * 1000);
            } catch (InterruptedException e) {
    
    
                //线程处于睡眠状态,外部调用该线程interrupt()方法,会抛出InterruptedException异常
                return;
            }
        }
    }

    public static void main(String[] args) {
    
    
        InterruptThread thread = new InterruptThread();
        thread.start();
        try {
    
    
            Thread.sleep(2 * 1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        thread.interrupt();
    }
}

猜你喜欢

转载自blog.csdn.net/zhaoqingquanajax/article/details/110098320