并发编程(5)Thread类的使用(sleep/yield/join)

Thread类中的方法:

.1)sleep

     强制当前正在执行的线程休眠指定的时间(线程转到阻塞状态),让出CPU给其他线程,在此期间,sleep不会释放对象锁,当休眠时间到期,恢复到可运行状态。关于sleep不会释放对象锁,请看下面例子:

public class TestSleep2 {
	private int i = 10;
    private Object object = new Object();
     
    public static void main(String[] args) throws IOException  {
    	TestSleep2 test = new TestSleep2();
        MyThread thread1 = test.new MyThread();
        MyThread thread2 = test.new MyThread();
        thread1.start();
        thread2.start();
    } 
    
    class MyThread extends Thread{
        @SuppressWarnings("static-access")
		@Override
        public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                   System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                   Thread.currentThread().sleep(10000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
}
i:11
线程Thread-0进入睡眠状态
线程Thread-0睡眠结束
i:12
i:13
线程Thread-1进入睡眠状态
线程Thread-1睡眠结束
i:14
从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行

.2)yield

调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程(也包括当前线程)有获取CPU执行时间的机会。

注意:调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

public class TestYield extends Thread{

	@SuppressWarnings("static-access")
	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
		  System.out.println("当前正在执行线程:"+Thread.currentThread().getName()+",i="+i);
		  Thread.currentThread().yield();
		}
	}
	
	public static void main(String[] args) {
		TestYield t1=new TestYield();
		TestYield t2=new TestYield();
		TestYield t3=new TestYield();
		t1.start();
		t2.start();
		t3.start();
	}
输出结果:
当前正在执行线程:Thread-0,i=0
当前正在执行线程:Thread-2,i=0
当前正在执行线程:Thread-1,i=0
当前正在执行线程:Thread-2,i=1
当前正在执行线程:Thread-0,i=1
当前正在执行线程:Thread-2,i=2
当前正在执行线程:Thread-1,i=1
当前正在执行线程:Thread-1,i=2
当前正在执行线程:Thread-0,i=2
当然,每次执行结果可能不一样,从上面可以看出,当前线程调用yield()方法之后,有可能执行其他线程,也有可能当前线程继续获取CPU权限。
.3)join

在一个线程里面调用另一个线程的join方法时,表示本线程阻塞直到另一个线程执行完毕。

主要用途:多个线程并行执行,如果某一个线程要用到一个或者多个线程的执行结果,或者某个线程必须等待一个或者多个线程执行完毕方能执行,可以采用join方法。

请看下面例子:

      

public class TestJoin {
	
	private int count=0;
	
	class Thread1 extends Thread{
		@SuppressWarnings("static-access")
		public void run(){
			while(count<100){
				count++;
				if(count==10){
					try {
						Thread.currentThread().sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			System.out.println("now Count-size :"+count);
		}
	}

	class Thread2 extends Thread{
		public void run(){
			System.out.println("count-size:"+count);
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		TestJoin t= new TestJoin();
		Thread1 t1=t.new Thread1();
		Thread2 t2=t.new Thread2();
		t1.start();
		//t1.join();
		t2.start();
	}

}
当注释掉t1.join();时,结果如下:

count-size:10
now Count-size :100
启用t1.join()时,结果如下:

now Count-size :100
count-size:100
可以看出没有调用t1.join()方法时,t2在t1进入休眠时已经执行完毕,调用了该方法时,t2等待t1执行完才开始执行。
实际上 join()方法调用的事wait方法,这个可以从源码得知,

 public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。  

由于wait方法会让线程释放对象锁,所以join方法同样会让线程释放对一个对象持有的锁。

参考资料:

              http://www.cnblogs.com/dolphin0520/p/3920357.html





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值