读书人

多线程1 几个方法区别

发布时间: 2012-11-08 08:48:11 作者: rapoo

多线程一 几个方法区别
sleep() 和 wait() 有什么区别? 搞线程的最爱
  sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞。
wait()是线程交互时,如果线程对一个同步对象(方法)x 发出一个wait()调用,该线程会暂停执行,被调对象(方法)进入等待状态,直到被唤醒或等待时间到。

Wait时别的线程可以访问锁定对象(调用wait,锁就撒手);
调用wait方法的时候必需锁定该对象;
Object提供的方法
Sleep时别的线程也不可以访问锁定对象(睡着也抱着锁);
Thread提供的方法
请参考下面2个例子就全明白了......


同步:
a.每个对象只有一把锁
b.一个线程访问同步方法时候,别的线程可以访问该对象的其他非同步的方法,而且也可以影响同步方法内部的变量。

例1:

public class TT implements Runnable {int b = 100;public synchronized void m1() throws Exception{b = 1000;Thread.sleep(1000);System.out.println("b = " + b);}public synchronized void m2() throws Exception {Thread.sleep(3000);b = 2000;}public void run() {try {m1();} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {TT tt = new TT();Thread t = new Thread(tt);t.start();tt.m2();System.out.println(tt.b);}}===输出结果有2中可能====如果主线程锁定当前对象,输出结果为:2000b = 1000如果子线程锁定当前对象,输出结果为:1000b = 1000


例2:范例名称:生产者--消费者问题
遇到互斥的问题时候如何解决得呢?
答:将互斥的2个操作放到同一个类的2个方法中,然后让这2个方法都加上synchronized关键字修饰


/* * 源文件名称:SyncTest.java
*要 点:
*1. 共享数据的不一致性/临界资源的保护
*2. Java对象锁的概念
*3. synchronized关键字/wait()及notify()方法
*/


package com.wlh;public class ProduceConsumer {       public static void main(String args[]){               SyncStack stack = new SyncStack();               Runnable p=new Producer(stack);               Runnable c = new Consumer(stack);               Thread t1 = new Thread(p);               Thread t2 = new Thread(c);               t1.start();               t2.start();       }   }       /**   * 支持多线程同步操作的堆栈的实现    * 因为只有一个线程能够锁定当前对象,而同步方法的执行前先锁定当前对象,   * 所以同一时刻,同步方法push和pop只能有一个在执行   * @author wulihai   */class SyncStack{        private int index = 0;       private char []data = new char[6];             public synchronized void push(char c){           if(index == data.length){           try{                   this.wait();           }catch(InterruptedException e){}           }           this.notify();           data[index] = c;           index++;       }       public synchronized char pop(){           if(index ==0){               try{                   this.wait();               }catch(InterruptedException e){}           }           this.notify();           index--;           return data[index];       }   }       class  Producer implements Runnable{       SyncStack stack;           public Producer(SyncStack s){           stack = s;       }       public void run(){           for(int i=0; i<20; i++){               char c =(char)(Math.random()*26+'A');//               stack.push(c);               System.out.println("produced:"+c);               try{                                                       Thread.sleep((int)(Math.random()*1000)); //随机休息,这样看起来生产和消费的产品个数都是随机的              }catch(InterruptedException e){               }           }       }   }       class Consumer implements Runnable{       SyncStack stack;           public Consumer(SyncStack s){           stack = s;       }       public void run(){           for(int i=0;i<20;i++){               char c = stack.pop();               System.out.println("消费:"+c);               try{                                                          Thread.sleep((int)(Math.random()*1000));//随机休息,这样看起来生产和消费的产品个数都是随机的                 }catch(InterruptedException e){               }           }       }   }  



死锁:当一个或多个进程等待系统资源,而系统资源又同时被此进程本身或者其它进程占用

例:结果2个线程谁都不打印输出数据
package com.wlh;public class DeadLock extends Thread {int flag=0;static Object o1=new Object();static Object o2=new Object();public DeadLock(int flag){this.flag=flag;}@Overridepublic void run() {if(this.flag==1){synchronized(o1){System.out.println(Thread.currentThread().getName()+"锁定对象o1");try {Thread.sleep(1000);//让另一个线程能进入另一块区域,锁定对象o2} catch (InterruptedException e) {e.printStackTrace();}synchronized(o2){System.out.print("this.flag="+this.flag);}}}if(this.flag==2){synchronized(o2){System.out.println(Thread.currentThread().getName()+"锁定对象o2");try {Thread.sleep(1000);//让另一个线程能进入另一块区域,锁定对象o1} catch (InterruptedException e) {e.printStackTrace();}synchronized(o1){System.out.print("this.flag="+this.flag);}}}}public  static void main(String []args){DeadLock d1=new DeadLock(1);DeadLock d2=new DeadLock(2);d1.start();d2.start();}}





Join方法:将某个子线程合并到主线程,即等子线程全部运行全部执行完之后才执行主线程
例1:
package com.wlh;public class TestJoin {  public static void main(String[] args) {    MyThread2 t1 = new MyThread2("子线程");    t1.start();     /*    try {    t1.join();    } catch (InterruptedException e) {}*/        for(int i=1;i<=10;i++){    try {Thread.sleep(1000);//当前线程休息1000秒System.out.println("i am main thread");} catch (InterruptedException e) {e.printStackTrace();}          }  }}class MyThread2 extends Thread {  MyThread2(String s){  super(s);  }    public void run(){    for(int i =1;i<=10;i++){      System.out.println("i am "+getName());      try {      sleep(1000);//当前线程休息1000秒      } catch (InterruptedException e) {      return;      }    }  }}


备注:子线程和主线程交替执行
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread


例2:在 t1.start()子线程就绪;之后添加t1.join(),则等t1线程执行完之后才执行主线程

package com.wlh;public class TestJoin {  public static void main(String[] args) {    MyThread2 t1 = new MyThread2("子线程");    t1.start();      try {    t1.join();    } catch (InterruptedException e) {}        for(int i=1;i<=10;i++){    try {Thread.sleep(1000);//当前线程休息1000秒System.out.println("i am main thread");} catch (InterruptedException e) {e.printStackTrace();}          }  }}class MyThread2 extends Thread {  MyThread2(String s){  super(s);  }    public void run(){    for(int i =1;i<=10;i++){      System.out.println("i am "+getName());      try {      sleep(1000);//当前线程休息1000秒      } catch (InterruptedException e) {      return;      }    }  }}

输出结果:

i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread



Yeild方法:当前线程让出CPU的时间给其他线程执行一会。注意:是让出一会儿,待会又回来了。。。


package com.wlh;public class TestYield {  public static void main(String[] args) {    MyThread3 t1 = new MyThread3("t1");    MyThread3 t2 = new MyThread3("t2");    t1.start(); t2.start();  }}class MyThread3 extends Thread {  MyThread3(String s){super(s);}  public void run(){    for(int i =1;i<=100;i++){      System.out.println(getName()+": "+i);      if(i%10==0){        yield();      }    }  }}

输出结果:只要一个线程执行到10的整数倍,必然让出CPU的时间给其他线程执行一会
t1: 1
t1: 2
t1: 3
t1: 4
t1: 5
t1: 6
t1: 7
t1: 8
t1: 9
t1: 10
t2: 1
t2: 2
t2: 3
t2: 4
t2: 5
t2: 6
t2: 7
t2: 8
t2: 9
t2: 10
t1: 11
t1: 12
t1: 13
t1: 14
t1: 15
t1: 16
t1: 17
t1: 18
t1: 19
t1: 20
t2: 11
t2: 12
t2: 13
t2: 14
t2: 15
...........
..............
...................

读书人网 >软件架构设计

热点推荐