java学习总结——线程的sleep、yield、join方法

一、sleep方法

      这个方法使用很多,理解也很简单。让线程处于等待状态(TIME_WAITING),同时不释放资源和锁。示例代码:

public class ThreadTest11 {

	public static void main(String[] args) throws Exception {
		   RunnableThread runnableThread = new RunnableThread(1);
		   Thread thread1 = new Thread(runnableThread);
		   Thread thread2 = new Thread(runnableThread);
		   thread1.start();
		   Thread.sleep(1000);
		   thread2.start();
		   
		   Thread.sleep(1000);
		   State state1 = thread1.getState(); //线程1等待锁,状态:TIME_WAITING
		   System.out.println("state1--"+state1); 
		   
		   State state2 = thread2.getState(); //因为线程1调用sleep方法没有释放锁,所以线程2等待锁,状态:BLOCKED
		   System.out.println("state2--"+state2); 
	}
}

//输出结果
//state1--TIMED_WAITING
//state2--BLOCKED

public class RunnableThread implements Runnable{
	
	private int number;

	public RunnableThread(int number) {
		this.number = number;
	}

	@Override
	public void run() {
		getLock();
	}
	
	private synchronized void getLock() {
		 try {
			TimeUnit.SECONDS.sleep(4);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
二、yield方法
      yield方法的作用是:线程放弃自己获得的时间片,然后继续等待CPU的时间片。这句话比较不容易理解。举一个“等公交车”的例子说明一下:

      当公交车到站时,会有两种情况;第一:公交车没有位置,没有乘客能够上车,大家继续等下一辆。第二:公交车有位置,乘客可以选择上车和不上车。在第二种情况下,当乘客选择不上车的时候(比如男朋友/女朋友没来,要等他/她一起),就会与其他乘客(没有机会上车)一起等待下一辆公交车。等到下一辆公交车来了,乘客还是可以再选择是否上车,可以无限的循环这个过程。

     yield方法的作用就跟上面的例子很类似。 当启动多个线程的之后,多个线程会竞争CPU的资源(时间片)。获得CPU资源(时间片)的线程就会被执行,没有获得CPU资源(时间片)的线程就只能等待,等待CPU分配给他资源(时间片)。而yield方法的作用是:线程放弃自己获得的时间片,然后继续等待CPU的时间片;就像乘客放弃自己上公交车的机会,继续等下一次公交车的情形一样。示例代码:

public class ThreadTest11 {

	public static void main(String[] args) throws Exception {
		   RunnableThread runnableThread = new RunnableThread(1);
		   Thread thread1 = new Thread(runnableThread);
		   Thread thread2 = new Thread(runnableThread);
		   thread1.setPriority(Thread.MIN_PRIORITY);  //将thread1的优先权设置为最小值
		   thread2.setPriority(Thread.MAX_PRIORITY);  //将thread2的优先权设置为最大值
		   thread1.setName("thread1");
		   thread2.setName("thread2");
		   thread1.start();
		   thread2.start();
	}
}

public class RunnableThread implements Runnable{
	
	private int number;

	public RunnableThread(int number) {
		this.number = number;
	}

	@Override
	public void run() {
		for(int i=0 ; i<3; i++){ //放大循环次数,效果会更明显
			if(Thread.currentThread().getName().equals("thread1")){
				Thread.yield();  //调用yield方法,放弃执行权利
			}
			System.out.println(Thread.currentThread().getName()+" -- "+i);
		}
	}
}

//输出结果:
/*执行结果的顺序不是固定的,但是可以发现大多数时候都是thread2优先于thread1执行完成
thread2 -- 0
thread2 -- 1
thread2 -- 2
thread1 -- 0
thread1 -- 1
thread1 -- 2
*/
上面的代码主要做了两件事:第一,创建了两个线程,分别赋予最大优先权和最小优先权,并启动。第二,每个循环打印出3以下的整数。当执行线程是thread1时,会调用yield方法。

       thread1调用了yield方法,也就是说thread1每打印一个数字之前都会放弃一次它获取到的CPU时间片(但是调用一次yield方法只会放弃一次时间片,当线程再次获得时间片的时候就会继续往下执行,调用yield方法一次是不会放弃两次时间片的),然后跟thread2一起等待下一个时间片。

        thread1的优先权是最小值,thread2的优先权是最大值。也就是说在同时竞争CPU时间片的时候,thread2有更大的概率获得时间片(就是当公交车来的时候,thread2有机会上车的概率比thread1大,但是仅仅只是概率大,并不能保证thread2一定比thread1先上车)。
       thread2的优先级比thread1高,同时thread1会调用yield方法。因此,执行结果中,thread2应该优先thread1执行(仅仅只是概率,并不一定保证优先)。对比上面的输出结果,也是符合的(可以对比多次执行的输出结果)。


三、join方法

        加入调用join方法的线程,并等待调用join方法的线程执行;根据传入的参数不同,等待的时间也不同。分别如下: 

          1、join(),等待加入的线程执行完成,再继续往下执行。

         2、join(2000),等待加入的线程执行,等待时间为2秒,无论加入的线程是否执行完成均继续往下执行

       3、join(2000,500000),这个方法与join(2000)的含义是一样的,只是传入的两个参数一个是毫秒(millis)单位,另外一个是纳秒(nanos)单位。

 实例代码:

public class ThreadTest12 {

	public static void main(String[] args) throws Exception { //这里是main线程
		   RunnableThread runnableThread = new RunnableThread(1);
		   Thread thread0 = new Thread(runnableThread);
		   Thread thread1 = new Thread(runnableThread);
		   thread0.start();
		   thread1.start();
		   
		   System.out.println("线程  : "+Thread.currentThread().getName()+" 执行完成");
	}
}

//输出结果
//线程  : main 执行完成 (没有调用join方法,启动线程之后就直接打印出了当前main线程的信息)
//线程  : Thread-1 执行完成
//线程  : Thread-0 执行完成

public class ThreadTest12 {

	public static void main(String[] args) throws Exception {
		   RunnableThread runnableThread = new RunnableThread(1);
		   Thread thread0 = new Thread(runnableThread);
		   Thread thread1 = new Thread(runnableThread);
		   thread0.start();
		   thread1.start();
		   
		   thread0.join();
		   thread1.join();
		   System.out.println("线程  : "+Thread.currentThread().getName()+" 执行完成");
	}
}

//输出结果
//线程  : Thread-0 执行完成
//线程  : Thread-1 执行完成
//线程  : main 执行完成(加入join方法,会等到thread0和thread1执行完成,在往下执行)

public class ThreadTest12 {

	public static void main(String[] args) throws Exception {
		   RunnableThread runnableThread = new RunnableThread(1);
		   Thread thread0 = new Thread(runnableThread);
		   Thread thread1 = new Thread(runnableThread);
		   thread0.start();
		   thread1.start();
		   
		   thread0.join(1000); //只等待一秒,无论线程thread0是否执行完均会继续往下执行
		   thread1.join(1000); 
		   System.out.println("线程  : "+Thread.currentThread().getName()+" 执行完成");
	}
}

//输出结果
//线程  : main 执行完成 (调用join方法,只等待一秒。而thread0和thread1执行完成需要2秒的时间)
//线程  : Thread-1 执行完成
//线程  : Thread-0 执行完成

public class RunnableThread implements Runnable{
	
	private int number;

	public RunnableThread(int number) {
		this.number = number;
	}

	@Override
	public void run() {
		try {
		    TimeUnit.SECONDS.sleep(2);
		    System.out.println("线程  : "+Thread.currentThread().getName()+" 执行完成");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值