您的位置:首页 > 编程语言

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

2016-03-15 16:32 543 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程