让线程按照顺序执行的8种方法,如何指定线程的执行顺序

  让线程按照顺序执行的8种方法,如何指定线程的执行顺序

  00-1010如何让线程按照自己指定的顺序执行?知道加入吗?利用执行程序池中线程的优先级和执行顺序的优先级?使用优先级概述

  00-1010在我们日常的多线程开发中,我们有时可能希望每个线程按照我们指定的顺序运行,而不是让CPU随机调度,这可能会给我们的日常开发工作带来不必要的麻烦。

  有了这个需求,引入了本文的标题,这样线程就可以按照自己指定的顺序运行了。

  有兴趣的同学可以猜想下列代码可能运行的结果:

  按照正常的理解,以上代码的执行顺序应该是:t1 t2 t3,但实际效果并不理想。

  下图为运行效果:

  

目录

join可能有些同学不陌生,这里就不详细介绍什么是join了。有问题的同学可以自行百度,谷歌。

 

  这里我就直接介绍如何使用join来达到我们想要看到的效果!

  这里主要利用Join的阻塞效应来达到我们的目的。从图中显示的运行结果可以看出,程序已经按照我们指定的顺序执行了,并且得到了预期的结果。

  其实,我们可以在这里深入思考,为什么加盟能达到预期的效果?接下来,让我们看看源代码:

  输入join源代码后,首先看到的是一个传入0个参数的join方法。在这里,选择继续进入。

  首先,你可以看到join方法是线程安全的。其次,可以和上图一起看。当传入参数为0时,它将调用wait(0)方法。有经验的同学应该能直接理解,就是在这里等。

  不过需要注意的是,这里的等待绝对不是等待调用者,而是被阻塞的主线程。T1、T2和T3只是子线程,当子线程结束运行时,主线程结束等待。

  这演示了join是如何工作的,也证明了join可以让我们在程序中达到预期的效果。

  除了join这种可以帮助我们控制程序中线程顺序的方式,还有其他的方式,比如我们用线程池来尝试一下。

  00-1010Executors是class under java.util.concurrent包下的一个线程池操作类,可以方便的为我们提供线程池操作。

  这里,我们使用Executors中的newSingleThreadExecutor()方法来创建单线程线程池。

  根据上图我们可以知道,使用newSingleThreadExecutor()方法仍然可以达到预期的效果。其实原理很简单。该方法的内部是一个基于FIFO的队列。也就是说,当我们依次将t1、T2和T3加入队列时,实际上只有线程t1处于就绪状态,T2和T3将被加入队列。当T1结束时,队列中的其他线程将继续执行。

  根据上面的空间,我们知道了如何让线程按照指定的方式运行。其实方法很多,我就不一一列举了。

  00-1010学习运算符时,读者知道运算符之间是有优先级的,知道运算符的优先级对程序开发有很好的作用。螺纹也是如此。每个线程都有一个优先级,Java虚拟机根据线程的优先级来决定线程的执行顺序,让多个线程合理共享CPU资源,不会发生冲突。

  00-1010在Java语言中,线程的优先级范围是1~10,值必须是1~10,否则会发生异常;优先级的默认值是5。优先级高的线程会先执行,执行完了就轮到优先级低的线程执行。如果优先级相同,那就轮流。

  可以在Thread类中使用setPriority()方法来设置线程的优先级。语法如下:

  public final void set priority(int new priority);如果想获得当前线程的优先级,可以直接调用getPriority()方法。语法如下:

  public final int get priority();

  00-1010简单了解了优先级之后,这里有一个简单的例子来演示如何使用优先级。

  例 1

  单独使用线程

  类和 Runnable 接口创建线程,并为它们指定优先级。

  

public class FirstThreadInput extends Thread{    public void run()    {        System.out.println("调用FirstThreadInput类的run()重写方法");    //输出字符串        for(int i=0;i<5;i++)        {            System.out.println("FirstThreadInput线程中i="+i);    //输出信息            try            {                Thread.sleep((int) Math.random()*100);    //线程休眠            }            catch(Exception e){}        }    }}

(2) 创建实现 Runnable 接口的 SecondThreadInput 类,实现 run() 方法。代码如下:

 

  

public class SecondThreadInput implements Runnable{    public void run()    {        System.out.println("调用SecondThreadInput类的run()重写方法");    //输出字符串        for(int i=0;i<5;i++)        {            System.out.println("SecondThreadInput线程中i="+i);    //输出信息            try            {                Thread.sleep((int) Math.random()*100);    //线程休眠            }            catch(Exception e){}        }    }}

(3) 创建 TestThreadInput 测试类,分别使用 Thread 类的子类和 Runnable 接口的对象创建线程,然后调用 setPriority() 方法将这两个线程的优先级设置为 4,最后启动线程。代码如下:

 

  

public class TestThreadInput{    public static void main(String[] args)    {        FirstThreadInput fti=new FirstThreadInput();        Thread sti=new Thread(new SecondThreadInput());        fti.setPriority(4);        sti.setPriority(4);        fti.start();        sti.start();    }}

(4) 运行上述代码,运行结果如下所示。

 

  

调用FirstThreadInput类的run()重写方法调用SecondThreadInput类的run()重写方法FirstThreadInput线程中i=0SecondThreadInput线程中i=0FirstThreadInput线程中i=1FirstThreadInput线程中i=2SecondThreadInput线程中i=1FirstThreadInput线程中i=3SecondThreadInput线程中i=2FirstThreadInput线程中i=4SecondThreadInput线程中i=3SecondThreadInput线程中i=4

 

  

由于该例子将两个线程的优先级都设置为 4,因此它们交互占用 CPU ,宏观上处于并行运行状态。

 

  重新更改 ThreadInput 类的代码、设置优先级。代码如下:

  

fti.setPriority(1);sti.setPriority(10);

重新运行上述代码,如下所示。

 

  

调用FirstThreadInput类的run()重写方法调用SecondThreadInput类的run()重写方法FirstThreadInput线程中i=0SecondThreadInput线程中i=0SecondThreadInput线程中i=1SecondThreadInput线程中i=2SecondThreadInput线程中i=3SecondThreadInput线程中i=4FirstThreadInput线程中i=1FirstThreadInput线程中i=2FirstThreadInput线程中i=3FirstThreadInput线程中i=4

 

  

以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: