让线程按照顺序执行的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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。