论坛首页 Java企业应用论坛

多线程一 几个方法区别

浏览 3589 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-11   最后修改:2009-02-26
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中可能====
如果主线程锁定当前对象,输出结果为:
2000
b = 1000
如果子线程锁定当前对象,输出结果为:
1000
b = 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;
	}
	@Override
	public 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
...........
..............
...................
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics