控制线程

join线程

Thread提供了让一个线程等待另一个线程完成的方法:join()方法。当在某个程序执行流中调用其他线程的join()方法
时,调用线程将被阻塞,知道被join方法加入的join线程完成为止。
join()方法通常由使用线程的程序调用,以将大问题划分为许多小问题。如下面程序:
[java]  view plain copy
  1. public class JoinThread extends Thread{  
  2.   
  3.     /*** 
  4.      * 提供一个有参数的构造器,用于设置该线程的名字 
  5.      * @param name 
  6.      */  
  7.     public JoinThread(String name){  
  8.         super(name);  
  9.     }  
  10.       
  11.     @Override  
  12.     public void run() {  
  13.         super.run();  
  14.         for(int i = 0;i<100;i++){  
  15.             System.out.println(getName() + " " + i);  
  16.         }  
  17.     }  
  18.       
  19.     public static void main(String[] args) {  
  20.         new JoinThread("新线程").start();  
  21.         for(int i=0;i<100;i++){  
  22.             if(i == 20){  
  23.                 JoinThread jt = new JoinThread("被Join的线程");  
  24.                 jt.start();  
  25.                   
  26.                 //main线程调用了jt线程的join方法,main线程必须等待jt执行结束之后才会向下执行  
  27.                 try {  
  28.                     jt.join();  
  29.                 } catch (InterruptedException e) {  
  30.                     e.printStackTrace();  
  31.                 }  
  32.                 System.out.println(Thread.currentThread().getName() + " " + i);  
  33.             }  
  34.         }  
  35.     }  
  36.       
  37. }  

上面程序中一共有3条线程,主方法开始时就启动了名为“新线程”的子线程,该子线程将会和main线程并发执行。当
主线程的循环变量i为20时,启动了名为“被join的线程”的线程,该线程不会和main线程并发执行,而是main线程必须等待
该线程执行结束之后才可以向下执行。 

join方法有3中重载的方法
== join():等待被join的线程执行完成
== join(long millis):等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内,被join的线程还没有
执行结束则不再等待。
== join(long millis,int nanos);等待被join的线程的时间最长为millis毫秒加上nanos微秒(千分之一毫秒)。
通常很少使用第三个方法,原因有两个:程序对时间的精度无须精确到千分之一毫秒!计算机硬件、操作系统本身
也无法精确到千分之一毫秒。

后台线程

有一种线程,它是后台运行的,它的任务是为其他的线程提供服务,这种线程被成为“后台线程”,又称为“守护线程”。
JVM的垃圾回收线程是典型的后台线程。
后台线程有个特征:如果所有的前台线程都死亡,后台线程会自动死亡。 
调用Thread对象的setDaemon(true)方法可将指定线程设置为后台线程。

线程睡眠:sleep

如果我们需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态sleep方法,
sleep方法有两种重载的方式:
static void sleep(long millis):让当前正在执行的线程暂停millis毫秒,并进入阻塞状态,该方法受到系统计时
器和线程调度器的精度和准确度的影响。
static void sleep(long millis,int nanos):让当前正在执行的线程暂停milis毫秒加nonas毫微秒,并进入阻塞
状态,该方法受到系统计时器和线程调度器的精度和准确度的影响。
与前面类似的是,程序很少调用第二种方法。 
当当前线程调用sleep方法进入阻塞状态后,其在sleep时间段内,该线程不会获得执行的机会,即使系统中没有其他
可运行的线程,处于sleep中的线程也不会运行,因此sleep方法常用来暂停程序的执行。
下面程序调用sleep方法来暂停主线程的执行,因为该程序只有一条主线程,当主线程进入sleep后,系统没有可执行的
线程,所以可以看到程序在sleep处暂停。

[java]  view plain copy
  1. public class TestSleep {  
  2.   
  3.     public static void main(String[] args) throws Exception{  
  4.         for(int i = 0;i<100;i++){  
  5.             System.out.println("当前时间:" + new Date());  
  6.             Thread.sleep(1000);  
  7.         }  
  8.     }  
  9. }  


线程让步:yield

yield()方法是一个和sleep方法有点相似的方法,它也是一个Thread类提供的一个静态方法,它也可以让当前正在执行
的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。yield只是让当前线程暂停一下,让系统的线程调度器
重新调度一次,完全可能的情况是:当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。
实际上,当某个线程调用了yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的
线程才会得到执行的机会。下面程序使用yield来让当前正在执行的线程暂停:
[java]  view plain copy
  1. public class TestYield extends Thread{  
  2.     public TestYield(){  
  3.           
  4.     }  
  5.     public TestYield(String name){  
  6.         super(name);  
  7.     }  
  8.     @Override  
  9.     public void run() {  
  10.         super.run();  
  11.         for(int i = 0;i<50;i++){  
  12.             System.out.println(getName() + " " + i);  
  13.             //当i=20的时候,使用yield方法让当前线程让步  
  14.             if(i == 20){  
  15.                 Thread.yield();  
  16.             }  
  17.         }  
  18.     }  
  19.     public static void main(String[] args) throws Exception{  
  20.         //启动两条并发线程  
  21.         TestYield ty1 = new TestYield("高级");  
  22.         //将ty1线程设置成最高优先级  
  23.         //ty1.setPriority(Thread.MAX_PRIORITY);  
  24.         ty1.start();  
  25.         TestYield ty2 = new TestYield("低级");  
  26.         //将ty2线程设置成最高优先级  
  27.         //ty2.setPriority(Thread.MIN_PRIORITY);  
  28.         ty2.start();  
  29.     }  
  30. }  


上面程序中的代码把设置优先级的两行给注释掉了,运行的效果图如下图:


反之,如果我们把那两行代码的注释取消,运行的效果图如下图: 

关于sleep方法和yield方法的区别如下:
== sleep方法暂停当前线程后,会给其他线程执行机会,不会理会其他线程的优先级。但yield方法只会给优先级相同,
或优先级更高的线程执行机会。
== sleep方法会将线程转入阻塞状态,直到经过阻塞时间才会转入就绪状态。而yield不会将线程转入阻塞状态,它只是
强制当前线程进入就绪状态。因此完全可能某个线程调用yield方法暂停之后,立即再次获得处理器资源被执行。
== sleep方法声明抛出了InterruptedException异常,所以调用sleep方法时要么捕捉该异常,要么显示声明抛出该异常。
而yield方法则没有声明抛出任何异常。
== sleep方法比yield方法更好的可移植性,通常不要依靠yield来控制并发线程的执行。

改变线程的优先级

每个线程执行时都具有一定的优先级,优先级高的线程获得较多的执行机会,而优先级低的线程则获得较少的执行机会。
每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,main线程具有普通优先级,由main线程
创建的子线程也有普通优先级。
Thread提供了setPriority(int newPriority)和getPriority()方法来设置和返回指定线程的优先级,其中setPriority
方法的参数可以是一个整数,范围是1~10之间,也可以使Thread类的三个静态变量:
== MAX_PRIORITY:其值时10.
== MIN_PRIORITY:其值是1.
== NORM_PRIORITY:其值是5.
下面程序使用了setPriority来改变主线程的优先级,并使用了该方法改变了两条线程的优先级,从而可以看到高优先级
的线程将的到更多的执行机会。

[java]  view plain copy
  1. public class PriorityThread extends Thread{  
  2.   
  3.     public PriorityThread(){  
  4.           
  5.     }  
  6.     public PriorityThread(String name){  
  7.         super(name);  
  8.     }  
  9.       
  10.     @Override  
  11.     public void run() {  
  12.         super.run();  
  13.         for(int i =0;i<50;i++){  
  14.             System.out.println(getName() + ",其优先级是:" + getPriority() + ",循环变量的值为:" + i);  
  15.         }  
  16.     }  
  17.       
  18.     public static void main(String[] args) {  
  19.         //改变主线程的优先级  
  20.         Thread.currentThread().setPriority(6);  
  21.         for(int i= 0;i<30;i++){  
  22.             if(i == 10){  
  23.                 PriorityThread low = new PriorityThread("低级");  
  24.                 low.start();  
  25.                 System.out.println("创建之初的优先级:" + low.getPriority());  
  26.                 //设置该线程为最低优先级  
  27.                 low.setPriority(Thread.MIN_PRIORITY);  
  28.             }  
  29.             if(i == 20){  
  30.                 PriorityThread high = new PriorityThread("高级");  
  31.                 high.start();  
  32.                 System.out.println("创建之初的优先级:" + high.getPriority());  
  33.                 //设置该线程优先级为最高级  
  34.                 high.setPriority(Thread.MAX_PRIORITY);  
  35.             }  
  36.               
  37.         }  
  38.     }  
  39.       
  40. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值