浏览 3589 次
锁定老帖子 主题:多线程一 几个方法区别
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-02-11
最后修改:2009-02-26
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 ........... .............. ................... 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |