Thread.yield( )

本文详细解析了Java中yield(), sleep()以及wait()等线程控制方法的区别与使用场景,对比了suspend()、resume()等旧方法的问题,并介绍了join()等其他线程控制函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

avayield(),sleep()以及wait()的区
往往混淆了三个函数的使用。
从操作系的角度os维护一个ready queue(就线列)。并且在某一cpuready queue中位于部的线程服
但是当前正在被服线程可能cpu的服务质量不好,于是提前退出,就是yield
或者当前正在被服线程需要睡一会,醒来后继续被服就是sleep
sleep方法不推荐使用,可用wait
线程退出最好自己实现,在运行状中一直检验一个状,如果个状态为真,就一直运行,如果外界更改了个状态变量,那么线程就停止运行。
sleep()使当前线入停滞状,所以sleep()线程在指定的时间内肯定不会行;yield()只是使当前线程重新回到可行状,所以yield()线程有可能在入到可行状上又被行。
sleep()
可使低的线程得到行的机会,当然也可以和高线程有行的机会;yield()只能使同线程有行的机会。
wait()后,线程会放掉它所占有的锁标,从而使线程所在象中的其它synchronized数据可被线程使用。
waite()notify()对对象的锁标行操作,所以它synchronized函数或synchronized block用。如果在non-synchronized函数或non-synchronized block用,然能编译,但在运行IllegalMonitorStateException的异常。
 
底明白多线程通信机制:
  线的通信
1.    
线程的几
线程有四,任何一个线程肯定中的一
1)    
生(New):线象已经产生,但尚未被启,所以无法行。如通new生了一个线象后没start()函数之前。
2)    
行(Runnable):个支持多线程的系都有一个排程器,排程器会从线程池中选择一个线程并启它。当一个线于可行状态时,表示它可能正线程池中等待排排程器启它;也可能它已正在行。如行了一个线象的start()方法后,线程就于可行状,但而易的是此时线程不一定正在行中。
3)    
死亡(Dead):当一个线正常束,它便于死亡状。如一个线程的run()函数行完线程就入死亡状
4)    
停滞(Blocked):当一个线于停滞状态时,系排程器就会忽略它,不行排程。当于停滞状线程重新回到可行状态时,它有可能重新行。如通过对一个线wait()函数后,线程就入停滞状,只有当两次对该线notifynotifyAll后它才能两次回到可行状
2.    class Thread下的常用函数函数
2.1    suspend()
resume()
1)    
suspend()函数,可使线入停滞状。通suspend()使线入停滞状后,除非收到resume()消息,否则该线程不会回可行状
2)    suspend()函数后,线程不会放它的锁标
11
    class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public synchronized void run(){
            if(shareVar==0){
                for(int i=0; i<5; i++){
                    shareVar++;
                    if(shareVar==5){
                        this.suspend();
 //1
                    }
                }
            }
            else{
                System.out.print(Thread.currentThread().getName());
                System.out.println(" shareVar = " + shareVar);
                this.resume();
 //2
            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start();
 //5
            //t1.start();
 //3
            t2.start();
 //4
        }
}
运行
t2 shareVar = 5
i.    
当代5)的t1生的线程运行到代1处时该线入停滞状。然后排程器从线程池中起代4)的t2生的线程,此shareVar0,所以else中的句。
ii.    
你会,那行代2)后不会使t1入可行状呢?正如前面所t1t2是两个不同象的线程,而代1)和(2)都只当前行操作,所以t1生的线行代1)的果是t1的当前线入停滞状;而t2生的线行代2)的果是把t2中的所有于停滞状线回到可行状
iii.    
在把代4)注掉,并去掉代3)的注,是不是就能使t1重新回到可行状呢?运行果是什也不出。这样呢?也你会认为,当代5)所生的线行到代1,它入停滞状;而代3)所生的线程和代5)所生的线程是属于同一个象的,那就当代3)所生的线行到代2,就可使代5)所生的线行回到可。但是要清楚,suspend()函数只是当前线入停滞状,但并不放当前线程所得的锁标。所以当代5)所生的线入停滞状态时,代3)所生的线程仍不能启,因当前象的锁标仍被代5)所生的线程占有。
2.2     sleep()
1)    sleep ()
函数有一个参数,通参数可使线程在指定的时间入停滞状,当指定的时间过后,线动进入可行状
2)    
sleep ()函数后,线程不会放它的锁标
12
    class TestThreadMethod extends Thread{
        class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public synchronized void run(){
            for(int i=0; i<3; i++){
                System.out.print(Thread.currentThread().getName());
                System.out.println(" : " + i);
                try{
                    Thread.sleep(100);
 //4
                }
                catch(InterruptedException e){
                    System.out.println("Interrupted");
                }
            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            TestThreadMethod t2 = new TestThreadMethod("t2");
            t1.start();
 (1
            t1.start();
 (2
            //t2.start();
 (3
        }
}
运行
t1 : 0
t1 : 1
t1 : 2
t1 : 0
t1 : 1
t1 : 2
果可明,然在run()行了sleep(),但是它不会象的锁标,所以除非代(1)线行完run()函数并象的锁标,否2)的线程永不会行。
                
如果把代2)注掉,并去掉代3)的注果将变为
t1 : 0
t2 : 0
t1 : 1
t2 : 1
t1 : 2
t2 : 2
由于t1t2是两个象的线程,所以当线t1sleep()入停滞,排程器会从线程池中用其它的可线程,从而t2线程被启
                
13
    class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public synchronized void run(){
            for(int i=0; i<5; i++){
                System.out.print(Thread.currentThread().getName());
                System.out.println(" : " + i);
                try{
                    if(Thread.currentThread().getName().equals("t1"))
                        Thread.sleep(200);
                    else
                        Thread.sleep(100);
                }
                catch(InterruptedException e){
                    System.out.println("Interrupted");
                }
            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            TestThreadMethod t2 = new TestThreadMethod("t2");
            t1.start();
            //t1.start();
            t2.start();
        }
    }
运行
t1 : 0
t2 : 0
t2 : 1
t1 : 1
t2 : 2
t2 : 3
t1 : 2
t2 : 4
t1 : 3
t1 : 4
由于线t1用了sleep(200),而线t2用了sleep(100),所以线t2于停滞状时间线t1的一半,从从果反映出来的就是线t2打印两倍次线t1才打印一次。
2.3    yield()
1)    
yield ()函数,可使线入可行状,排程器从可行状线程中重新行排程。所以用了yield()的函数也有可能上被行。
2)    
yield ()函数后,线程不会放它的锁标
14
    class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public synchronized void run(){
            for(int i=0; i<4; i++){
                System.out.print(Thread.currentThread().getName());
                System.out.println(" : " + i);
                Thread.yield();
            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            TestThreadMethod t2 = new TestThreadMethod("t2");
            t1.start();
            t1.start();
 //1
            //t2.start();
 (2
        }
}
运行
t1 : 0
t1 : 1
t1 : 2
t1 : 3
t1 : 0
t1 : 1
t1 : 2
t1 : 3
果可知yield()并不会象的锁标
                
如果把代1)注掉,并去掉代2)的注
t1 : 0
t1 : 1
t2 : 0
t1 : 2
t2 : 1
t1 : 3
t2 : 2
t2 : 3
果可知,t1线用了yield(),但它上又被行了。
2.4    sleep()
yield()的区
1)    sleep()
使当前线入停滞状,所以sleep()线程在指定的时间内肯定不行;yield()只是使当前线程重新回到可行状,所以yield()线程有可能在入到可行状上又被行。
2)    sleep()
可使低的线程得到行的机会,当然也可以和高线程有行的机会;yield()只能使同线程有行的机会。
15
    class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public void run(){
            for(int i=0; i<4; i++){
                System.out.print(Thread.currentThread().getName());
                System.out.println(" : " + i);
                //Thread.yield();
 (1
                /* 
2 */
                try{
                    Thread.sleep(3000);
                }
                catch(InterruptedException e){
                    System.out.println("Interrupted");
                }

            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            TestThreadMethod t2 = new TestThreadMethod("t2");
            t1.setPriority(Thread.MAX_PRIORITY);
            t2.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
        }
}
运行
t1 : 0
t1 : 1
t2 : 0
t1 : 2
t2 : 1
t1 : 3
t2 : 2
t2 : 3
果可,通sleep()可使级较低的线程有行的机会。掉代2),并去掉代1)的注
t1 : 0
t1 : 1
t1 : 2
t1 : 3
t2 : 0
t2 : 1
t2 : 2
t2 : 3
yield(),不同线程永不会得到行机会。
2.5    join()
使join()线行完后才能行其它线程,在一定意上,它可以实现的功能。
16
    class TestThreadMethod extends Thread{
        public static int shareVar = 0;
        public TestThreadMethod(String name){
            super(name);
        }
        public void run(){
            for(int i=0; i<4; i++){
                System.out.println(" " + i);
                try{
                    Thread.sleep(3000);
                }
                catch(InterruptedException e){
                    System.out.println("Interrupted");
                }
            }
        }
    }
    public class TestThread{
        public static void main(String[] args){
            TestThreadMethod t1 = new TestThreadMethod("t1");
            t1.start();
            try{
                t1.join();
            }
            catch(InterruptedException e){}
            t1.start();
        }
}
运行
 0
 1
 2
 3
 0
 1
 2
 3


3. class
 Object下常用的线程函数
wait()
notify()notifyAll()三个函数由java.lang.Object提供,用于协调多个线共享数据的存取。
3.1 wait()notify()notifyAll()
1) wait()
函数有两形式:第一形式接受一个毫秒,用于在指定时间长度内线程,使线入停滞状。第二形式参数,代表waite()notify()notifyAll()之前会持停滞。
2) 
一个notify(),会从线程等待池中移走任意一个线程,并把它放到锁标志等待池中;当一个notifyAll(),会从线程等待池中移走所有该对象的所有线程,并把它放到锁标志等待池中。
3) 
wait()后,线程会放掉它所占有的锁标,从而使线程所在象中的其它synchronized数据可被线程使用。
17
下面,我11中的例子行修改
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
if(shareVar==0){
for(int i=0; i<10; i++){
shareVar++;
if(shareVar==5){
try{
this.wait();
 //4
}
catch(InterruptedException e){}
}
}
}
if(shareVar!=0){
System.out.print(Thread.currentThread().getName());
System.out.println(" shareVar = " + shareVar);
this.notify();
 //5
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start();
 //1
//t1.start();
 (2
t2.start();
 //3
}
}
运行
t2 shareVar = 5
t1t2是两个不同象,所以线t2用代5)不能线t1如果去掉代2)的注,并注掉代3),
t1 shareVar = 5
t1 shareVar = 10
是因,当代1)的线行到代4,它入停滞状,并象的。接着,代2)的线run(),由于此shareVar值为5,所以行打印句并用代5)使代1)的线入可行状,然后代2)的线束。当代1)的线程重新行后,它接着for()一直到shareVar=10,然后打印shareVar
3.2 wait()notify()synchronized
waite()
notify()对对象的锁标行操作,所以它synchronized函数或synchronized block用。如果在non-synchronized函数或non-synchronized block用,然能编译,但在运行IllegalMonitorStateException的异常。
18
class TestThreadMethod extends Thread{
public int shareVar = 0;
public TestThreadMethod(String name){
super(name);
new Notifier(this);
}
public synchronized void run(){
if(shareVar==0){
for(int i=0; i<5; i++){
shareVar++;
System.out.println("i = " + shareVar);
try{
System.out.println("wait......");
this.wait();
}
catch(InterruptedException e){}
}
}
}
}
class Notifier extends Thread{
private TestThreadMethod ttm;
Notifier(TestThreadMethod t){
ttm = t;
start();
}
public void run(){
while(true){
try{
sleep(2000);
}
catch(InterruptedException e){}
/*1 
要同的不是当前象的做法 */
synchronized(ttm){
System.out.println("notify......");
ttm.notify();
}
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
t1.start();
}
}
运行
i = 1
wait......
notify......
i = 2
wait......
notify......
i = 3
wait......
notify......
i = 4
wait......
notify......
i = 5
wait......
notify......
4. wait()
notify()notifyAll()suspend()resume()sleep()讨论
4.1 
函数的区
1) wait()
使当前线入停滞状态时放当前线程所占有的锁标,从而使线象中的synchronized源可被象中线程使用;而suspend()sleep()使当前线入停滞状态时不会放当前线程所占有的锁标
2) 
前一函数必synchronized函数或synchronized block用,否在运行错误;而后一函数可以non-synchronized函数和synchronized block用。
4.2 函数的取舍
Java2
已不建使用后一函数。因wait()不会放当前线程所取得的锁标这样很容易造成
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值