java 线程 --- join,sleep,yield 基础学习

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/android_freshman/article/details/53887570

java 的线程支持提供了一些便捷的工具方法,通过这些工具方法可以很好的控制线程的执行。


1.join 线程

Thread 提供了让一个线程等待另一个线程的方法 — join()方法。当在某个程序执行流中调用其他线程的join()方法,调用的线程将被阻塞,直到被join()加入的join 线程执行完成。

相关代码:

    public class JoinThread extends Thread {

        /**
         * 设置线程的名字
         */
        public JoinThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for(int i=0;i<N;i++){
                Log.d(TAG,getName()+", i="+i);
            }
        }
    }

    private void starJoinThread(){
        //启动子线程
        new JoinThread("Join的新线程").start();

        for(int i=0; i<N; i++){
            if(i==20){
                JoinThread joinThread = new JoinThread("被Join的线程");
                joinThread.start();

                //主线程调用了 JoinThread 线程的 join 方法,主线程必须等join方法执行完,才会继续往下执行
                try {
                    joinThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            Log.d(TAG,"主线程 i="+i);
        }
    }

执行结果:

这里写图片描述

总共存在3个线程,一个主线程 ,一个join线程,一个被join 的线程,在i<20 的时候,主线程 和 join新线程 并发执行。
当 i=20 时,主线程启动了 被Join的线程 ,该线程不会和主线程并发执行,主线程必须等到 被Join的线程 的线程执行完才会向下执行。

join()方法通常由使用线程的程序调用,将大问题划分为许多小问题,将每个小问题分配一个线程。当所有的小问题处理完成之后,在调用主线程进一步的操作。


2.sleep

如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用 Thread.sleep()的方法来实现。

当当前线程调用sleep()方法进入阻塞状态后,在其睡眠的时间内,该线程不会获得执行的机会,即使系统中没有其他可执行的线程,处于sleep()中的线程也不会执行,一次sleep()常用来暂停程序的执行。

相关代码:

private void starSleepTest(){
        for(int i=0; i<10; i++){

            Log.d(TAG,"当前时间:"+new Date());
            try {
                //当前线程暂停一秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

执行结果:

这里写图片描述

暂停一秒执行,每条结果的间隔是 一秒。


3.线程让步 yield

yield() 是和 sleep()方法有点相似的方法。它也是线程提供的一个静态的方法,它可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。 yield()只是让当前的线程暂停一下,让系统的线程调度器重新调度一次,有种情况是:当某个线程调用了yield()方法暂停之后,线程调度器有将其调度出来重新执行。

当某个线程调用了 yield() 方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会。

相关代码:

public class YieldThread extends Thread{

        public YieldThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for(int i=0;i<50;i++){
                Log.d(TAG,getName()+", i="+i);

                //当i=20 的时候,yield()的方法使当前线程让步
                if(i==20){
                    Thread.yield();
                }
            }
        }
    }

    private void starYieldThread(){
        //启动 2个并发线程
        YieldThread yt1 = new YieldThread("高级");

        //将高级线程的优先级设置为最高
//        yt1.setPriority(Thread.MAX_PRIORITY);
        yt1.start();

        YieldThread yt2 = new YieldThread("低级");

        //将低级线程的优先级设置为最低
//        yt2.setPriority(Thread.MIN_PRIORITY);
        yt2.start();
    }

执行结果:

这里写图片描述

这里写图片描述

因为低级和高级并没有设置具体的优先级,所有2者的优先级是一样的,在高级 i=20的时候,让步,低级得到执行机会,下面将会是并发执行。当低级 i=20的时候,没有其他线程了,就继续执行自己,没有阻塞该线程。

private void starYieldThread(){
        //启动 2个并发线程
        YieldThread yt1 = new YieldThread("高级");

        //将高级线程的优先级设置为最高
        yt1.setPriority(Thread.MAX_PRIORITY);
        yt1.start();

        YieldThread yt2 = new YieldThread("低级");

        //将低级线程的优先级设置为最低
        yt2.setPriority(Thread.MIN_PRIORITY);
        yt2.start();
    }

将代码设置优先级之后的调用结果:

这里写图片描述

高级优先级的线程调用yield()方法暂停之后,系统中没有与之优先级相同的,或更高优先级的线程,所以该线程继续执行。


4. yield 和 sleep 对比

1.sleep() 方法暂停当前线程后,会给其他线程执行机会,不会理会其他线程的优先级;当yield()方法只会给优先级相同,或优先级更高的线程执行机会;

2.sleep()方法会将线程进入阻塞状态,知道经过阻塞时间才会转入就绪状态,yield()方法不会将线程转让阻塞状态,它只会强制当前线程进入就绪状态。

3.sleep()方法声明抛出了 InterruptedException 异常,所以sleep()方法要么捕获该异常,要么显示声明抛出该异常。yield() 方法则没有抛出任何异常。

4.sleep()方法比yield()有更好的可移植性,通常不建议使用yield()方法来控制并发线程执行。

猜你喜欢

转载自blog.csdn.net/android_freshman/article/details/53887570