java多线程学习(二)线程的基本方法

sleep方法(线程休眠) 

sleep(long millis)作用是让当前线程休眠指定的毫秒,使当前线程进入阻塞状态,期间会让出cpu的资源,但不会释放已获得的锁.

到达指定时间后,线程会从阻塞状态变成 可运行状态,重新竞争cpu的资源

static void sleep(long millis) 

这是Thread类中的静态方法。这里提到“当前线程”的概念,谈谈我的理解:

关于“当前线程”的理解:
即Thread.currentThread()返回的线程,也可以说是正在执行sleep方法的线程。

下面来看个例子:

public class myThread03 extends Thread{
    public  void run(){
        System.out.println(this.getName());
        System.out.println(Thread.currentThread().getName());
    }
    public static void main(String[]args){
        myThread03 mt0 = new myThread03();
        myThread03 mt1 = new myThread03();

        mt0.start();
        mt1.start();
    }
}

这里创建并启动了两个线程,两个线程都分别执行run方法里的语句。当 Thread-0 线程访问run方法时,Thread-0对于被访问的run方法来说就是当前线程。当然,线程都是并发执行的,Thread-1线程同时也在访问run方法,那么对于被Thread-1访问的run方法,Thread-1就是当前线程。 所以,当前线程不能从字面上理解为某个时间段里正在运行的线程,因为线程都是并发的,一段时间内有多个线程在同时执行。

现在来看看 sleep方法的实例:

public class myThread3 extends Thread {
    @Override
    public void run(){
        try{
            System.out.println("begin = " + System.currentTimeMillis());
            System.out.println(Thread.currentThread().getName()+"开始执行");
            //使线程休眠2000ms
            Thread.sleep(2000);// 使用该静态方法需要捕获一个名为InterruptedException的异常
            System.out.println(Thread.currentThread().getName()+"结束执行");
            System.out.println("end = " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    public static void main(String[] args)
    {
        myThread3 mt = new myThread3();
        mt.start();
    }

}

运行可以看到,“开始休眠”和“休眠结束”之间隔了2秒钟,即 2000毫秒。

线程中断

void interrupt();//像线程发送中断请求,线程的中断状态将被设置成true。如果目前该线程被一个sleep调用堵塞,那么,就会抛出InterruptedException异常
static boolean interrupted() //测试当前线程是否被中断,注意,这是一个静态的方法。而且这一调用会产生副作用:它会将当前的线程的中断状态重置为false。
boolean isInterrupted()  //测试线程是否被中断,这一调用不改变线程的中断状态

调用interrupt()方法后,线程中断,该线程就不能继续执行了。

来看下面这个例子:

public class myThread05 extends  Thread {
    public void run(){
        int num = 0;
        while (isInterrupted()==false){ // 如果线程中断状态为false,则一直执行
            System.out.println("第"+num+"次执行");
            num++;
        }
    }
    public static void main(String[] args) throws InterruptedException {
     myThread05 mt = new myThread05();
     mt.start(); 
     Thread.sleep(200); // 让主线程休眠0.2秒,子线程继续执行
     mt.interrupt(); // 申请中断线程,中断状态设置为true
    }
}

yield方法 (线程让步)

暂时执行当前线程,并让出cpu资源(不会释放锁).当前线程会进入等待列表,和等待列表中的其他线程重新一起竞争cpu的资源 

所以执行yield方法的效果等价于当前线程把cpu时间片用完,从运行状态返回到就绪状态

public class myThread05 extends  Thread {
    public void run(){

        long begin = System.currentTimeMillis();
        for (int i=0;i<50000000;i++){
           Thread.yield(); //线程暂停,让出cpu资源,重新开始执行的时间不确定
        }
        long end = System.currentTimeMillis();
        long time=end-begin;
        System.out.println(Thread.currentThread().getName()+ "执行完毕,花费时间为"+ time);
    }
    public static void main(String[] args) throws InterruptedException {
        myThread05 mt = new myThread05();
        myThread05 mt1 = new myThread05();
        myThread05 mt2 = new myThread05();
        mt.start();
        mt1.start();
        mt2.start();

    }
}

运行结果如下:

耗费的时间很长,三个线程的执行耗费的时间差距也很大。(可以把for循环里的 Thread.yield() 删除重新运行,运行结果差别很大)

join方法 (线程合并)

暂停当前线程的运行,等待指定线程完成后在执行当前线程,执行起来的效果就好像是把指定线程合并到了当前线程. 

void join(); 等待该线程终止
void join(long millis);等待该线程终止,等待的时间最长为 millis 毫秒。

 注意点:

    - join方法必须在线程start方法调用之后才有意义

    - join方法可以传入一个参数,如 在A线程中调用 B.join(10),表示A线程会等待B线程10ms后运行,10ms后,A、B线程并行执行.join()等价于join(0),表示A线程等待B线程无限时间,直到B线程执行结束

    - A线程调用 B.join()后,在B线程执行过程中,如果A线程发送了中断会抛出异样(但如果B中断不会报异常)

    - join内部实现是调用wait()方法实现,所以调用join方法会释放锁

 

例子: 要求创建 a,b,c三个线程,并规定让 线程a,线程b,线程c顺序执行完成

public class myThread5 extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("线程a开始执行");
            Thread.sleep(500);
            System.out.println("线程a结束执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        myThread5 a =new myThread5();
       Thread b  = new Thread(()->{
           try {
               System.out.println("线程b开始执行");
               //执行完a线程,再继续往下执行
               a.join();
               System.out.println("线程b结束执行");
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       });
        Thread c  = new Thread(()->{
            try {
                System.out.println("线程c开始执行");
                //执行完b线程,再继续往下执行
                b.join();
                System.out.println("线程c结束执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        a.start();
        b.start();
        c.start();;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值