Thread.yield( )

ava yield(),sleep() 以及 wait() 的区
往往混淆了 三个函数的使用。
从操作系 的角度 os 维护 一个 ready queue (就 线 列)。并且在某一 cpu ready 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() 函数后, 线 程就 入停滞状 ,只有当两次 对该线 notify notifyAll 后它才能两次回到可 行状
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 生的 线 程,此 shareVar 0 ,所以 else 中的 句。
ii.    
你会 ,那 行代 2 )后 不会使 t1 入可 行状 呢?正如前面所 t1 t2 是两个不同 象的 线 程,而代 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
由于 t1 t2 是两个 象的 线 程,所以当 线 t1 sleep() 入停滞 ,排程器会从 线 程池中 用其它的可 线 程,从而 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
t1 t2 是两个不同 象,所以 线 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() 不会 放当前 线 程所取得的 锁标 这样 很容易造成
 
 

你可能感兴趣的:(Thread.yield( ))