线程的基本操作

Thread.join的使用

Thread.join是什么

Thread.join的作用是保证线程执行结果的可见性。

package com.gupaoedu.p5;

public class ThreadJonDemo {
    private static int x=0;
    private static int i=0;
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                //阻塞操作
                i = 1;
                x = 2;
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                i = x + 2;
            }
        });
        //两个线程的执行顺序,
        t1.start();
        t1.join(); //t1线程的执行结果对于t2可见(t1线程一定要比t2线程优先执行) --- 阻塞
        t2.start();
        Thread.sleep(1000);
        System.out.println("result:"+i);

    }
}

Thread.join的原理

在这里插入图片描述
Thread.join的本质其实就是wait/notifyall。它会使当前线程处于等待状态,直到调用join方法的线程执行完毕,当前线程才会被唤醒。

Thead.join的源码

// 源码
if (millis == 0L) {
    while(this.isAlive()) {
        this.wait(0L);
    }
}

notifyall唤醒方法是在JVM底层实现的,所以看不到源码,当线程执行结束后,JVM底层会调用notifyall唤醒等待状态的线程。

Thread.sleep的作用

Thread.sleep是什么

使线程暂停执行一段时间,直到等待的时间结束才恢复执行或在这段时间内被中断。

Thread.sleep的工作流程

  1. 挂起线程并修改其状态;
  2. 用sleep()提供的参数来设置一个定时器;
  3. 当时间结束,定时器会触发,内核收到中断后修改线程的运行状态。线程会被标志为就绪状态等待调度。
package com.gupaoedu.p5;

public class SleepDemo extends Thread{
    public static void main(String[] args) {
        new SleepDemo().start();
    }
    @Override
    public void run() {
        System.out.println("begin:"+System.currentTimeMillis());
        try {
            Thread.sleep(3000); //睡眠3秒
            System.out.println("end:"+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

睡眠的时间一定是大于等于设置的时间,因为睡眠时间结束后线程不会立即运行,需要等到CPU进行调度。

wait和notify的使用

wait和notify的作用

多个线程在处理同一个资源时,可以用到wait和notify来实现线程间的通信。因为多个线程处理同一个资源,所以需要配合synchronized来使用。
wait():让线程处于等待状态。这时线程会释放锁,并存入到线程池中。
notify():唤醒线程池中的第一个线程。

Thread.interrupt和Thread.interrupted

interrupt方法的作用

当其他线程通过调用当前线程的interrupt方法,表示向当前线程打个招呼,告诉他可以中断线程了,至于什么时候中断,取决于线程自己。

如何正确终止一个线程

让线程正确的终止就是等线程运行完run方法,这是一种友好的方式,而不是直接把线程杀掉。
正确的方式:
Thread.interrupted
Thread.interrupt

错误的方式:
Thread.stop 类似于 kill -9

以下代码如何让线程终止?

public class StopDemo {

    public static void main(String[] args) {
        Thread t1 = new Thread(new StopThread());
        t1.start();
    }

    static class StopThread implements Runnable{
        @Override
        public void run() {
            while (true){
                System.out.println("持续运行!!!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

使用interrupt方法

public static void main(String[] args) {
    Thread t1 = new Thread(new StopThread());
    t1.start();
    t1.interrupt(); // 设置中断标识为 true
}

static class StopThread implements Runnable{
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){ // 判断中断标识,默认为false
            System.out.println("持续运行!!!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程的run方法不能正常执行完成有2种情况,死循环阻塞状态下。以上是死循环的解决方式,阻塞状态下中断线程的方式如下:

public static void main(String[] args) {
    Thread t1 = new Thread(new StopThread());
    t1.start();
    t1.interrupt();
}

static class StopThread implements Runnable{
    @Override
    public void run() {
        try {
            // 当线程处于阻塞状态时,调用该线程的interrupt方法会使线程抛出InterruptedException异常
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

当线程在阻塞状态时,调用该线程的interrupt方法会唤醒该线程并抛出InterruptedException异常来响应客户端的中断请求。

interrupted方法的作用

Thread.interrupted()对设置中断标识的线程复位,并且返回当前的中断状态。

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(()->{
        while (true){
            // true 表示被中断过
            if(Thread.currentThread().isInterrupted()){
                System.out.println("before:" + Thread.currentThread().isInterrupted());
                Thread.interrupted(); // 对中断标识复位false,并返回当前的中断状态
                System.out.println("after:" + Thread.currentThread().isInterrupted());
            }
        }
    });
    thread.start();
    TimeUnit.SECONDS.sleep(1);
    thread.interrupt(); // 设置中断标识为true
}

执行结果:

before:true
after:false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值