1.采用此种形式主要是:解决线程死锁的情况。
2.信号灯法:目标生产一个消费一个
1 package TestThread; 2 //生产者和消费者共同使用同一个场景Movie在任何时刻只能在同一时间上对MOvie场景的访问 3 public class Movie { 4 private String pic; 5 private boolean flag=true; 6 //采用信号灯的形式,flag=1生产,flag=0消费 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 //共同的资源 10 Movie m=new Movie(); 11 //d多线程: 12 Player p1=new Player(m); 13 Consumer c1=new Consumer(m); 14 new Thread(p1).start(); 15 new Thread(c1).start(); 16 } 17 18 public synchronized void play(String pic){ 19 if(!flag) 20 {//生产者没有生产 21 try{ 22 this.wait(); 23 } 24 catch(InterruptedException e) 25 { 26 e.printStackTrace(); 27 } 28 } 29 this.notify(); 30 31 this.pic=pic; 32 try { 33 Thread.sleep(100); 34 } catch (InterruptedException e) { 35 // TODO Auto-generated catch block 36 e.printStackTrace(); 37 } 38 System.out.println("生产者-->"+this.pic); 39 this.flag=false; 40 } 41 42 public synchronized void watcher(){ 43 if(flag) 44 { 45 try { 46 this.wait(); 47 } catch (InterruptedException e) { 48 // TODO Auto-generated catch block 49 e.printStackTrace(); 50 } 51 } 52 this.notify();//唤醒消费者 53 54 try { 55 Thread.sleep(100); 56 } catch (InterruptedException e) { 57 // TODO Auto-generated catch block 58 e.printStackTrace(); 59 } 60 System.out.println("消费者--->"+pic); 61 this.flag=true; 62 } 63 64 } 65 66 //生产者 67 class Player implements Runnable{ 68 private Movie m; 69 70 public Player(Movie name) 71 { 72 this.m=name; 73 } 74 public void run() 75 { 76 for(int i=0;i<20;i++) 77 { 78 if(i%2==0) 79 { 80 m.play("左青龙"); 81 } 82 else 83 { 84 m.play("右白虎"); 85 } 86 } 87 } 88 } 89 90 class Consumer implements Runnable{ 91 private Movie m; 92 93 public Consumer(Movie m) 94 { 95 this.m=m; 96 } 97 public void run(){ 98 for(int i=0;i<20;i++) 99 { 100 m.watcher(); 101 } 102 } 103 }
3.用三个线程A,B,C轮换打印12345 678910 11、12、 13、14、15
第一种方法采用最原始synchronized,notify(),wait() ---这种方式采用原始方法,在jdk1.5之后的并发编程中出现了LOCk和其他线程概念(还要在学习)
1 package ThreadTest; 2 //用这种方法不在main函数中将pn写成全局变量这样导致id,id1,id2值发生修改 3 public class NUmbelPrint implements Runnable{ 4 static int state=1; 5 static int n=1; 6 private int id=0,id1=0,id2=0; 7 static NUmbelPrint pn=new NUmbelPrint(); 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 pn.id=1;new Thread(pn).start();try { 11 Thread.sleep(20); 12 } catch (InterruptedException e) { 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 } 16 pn.id=0;pn.id1=2;new Thread(pn).start(); 17 try{ 18 Thread.sleep(20); 19 } catch (InterruptedException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } 23 pn.id1=0;pn.id=0;pn.id2=3;new Thread(pn).start(); 24 try{ 25 Thread.sleep(20); 26 } catch (InterruptedException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 31 } 32 public void run() 33 { if(id==1) 34 work(id); 35 if(id1==2) 36 work1(id1); 37 if(id2==3) 38 work2(id2); 39 } 40 public void work(int temp){ 41 for(int i=0;i<5;i++) 42 { 43 synchronized (pn){ 44 while(state !=temp) 45 { 46 try { 47 this.wait(); 48 } catch (InterruptedException e) { 49 // TODO Auto-generated catch block 50 e.printStackTrace(); 51 } 52 } 53 for(int j=0;j<5;j++) 54 { 55 System.out.println(Thread.currentThread().getName()+"线程 "+n++); 56 } 57 state=2; 58 pn.notifyAll(); 59 if(i==4) 60 System.out.println("线程1"+state); 61 } 62 } 63 } 64 public void work1(int temp){ 65 for(int i=0;i<=5;i++){ 66 synchronized (pn){ 67 while(state !=temp) 68 { 69 try { 70 this.wait(); 71 } catch (InterruptedException e) { 72 // TODO Auto-generated catch block 73 e.printStackTrace(); 74 } 75 } 76 for(int j=0;j<5;j++) 77 { 78 System.out.println(Thread.currentThread().getName()+"线程 "+n++); 79 } 80 state=3; 81 pn.notifyAll(); 82 } 83 if(i==4) 84 System.out.println("线程2"+state); 85 } 86 } 87 public void work2(int temp){ 88 for(int i=0;i<5;i++){//第三个线程运行了4次 89 synchronized (pn){ 90 while(state !=temp) 91 { 92 try { 93 this.wait(); 94 } catch (InterruptedException e) { 95 // TODO Auto-generated catch block 96 e.printStackTrace(); 97 } 98 } 99 for(int j=0;j<5;j++) 100 { 101 System.out.println(Thread.currentThread().getName()+"线程 "+n++); 102 } 103 state=1; 104 pn.notifyAll(); 105 } 106 107 System.out.println("线程3--"+state+"---"+i); 108 } 109 } 110 } 111 //为什么最后一次中会0 1 0,因为线程1结束后就没有了,在整个程序中只有俩个线程,所以1 2 3修改成1 2,现在只有两个线程 112 //在这里竞争,所以最后才会出现0 1 0,线程发生变化
如果采用JDk1.5包中LOck和Condition并发包,对于run方法的实现有两种方式,第一种重载,直接在Thread中写入,第二种调用一个new Runable的实例
下面采用调用的是newRunnable 方法,与之前讲的使用Runnable接口大同小异,简单的使用继承Thread类的方法
1 package JavaLockPackage; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 //三个线程轮换打印12345 678910,。。。。。有序的打印直到75 7 public class LockAndConditionExam { 8 private static int n=1; 9 private static int state=1; 10 11 private static ReentrantLock lock1=new ReentrantLock(); 12 //获取其中的三个分支线程 13 private static Condition c1=lock1.newCondition(); 14 private static Condition c2=lock1.newCondition(); 15 private static Condition c3=lock1.newCondition(); 16 //的是一个实例,必须要加上static关键字,不然会成为class类,使用的new Runnable 接口方式 17 private static class CreateThread1 implements Runnable{ 18 public void run() 19 { 20 for(int i=0;i<5;i++) 21 { try{ 22 lock1.lock(); 23 while(state!=1) 24 { 25 try{ 26 c1.await(); 27 28 } 29 catch(InterruptedException e) 30 { 31 e.printStackTrace(); 32 } 33 } 34 for(int j=0;j<5;j++) 35 { 36 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 37 } 38 System.out.println(); 39 state=2; 40 c2.signal(); 41 42 } 43 finally{ 44 lock1.unlock(); 45 } 46 47 } 48 } 49 } 50 51 private static class CreateThread2 implements Runnable{ 52 public void run() 53 { 54 for(int i=0;i<5;i++) 55 { try{ 56 lock1.lock(); 57 while(state!=2) 58 { 59 try{ 60 c2.await(); 61 62 } 63 catch(InterruptedException e) 64 { 65 e.printStackTrace(); 66 } 67 } 68 for(int j=0;j<5;j++) 69 { 70 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 71 } 72 System.out.println(); 73 state=3; 74 c3.signal(); 75 76 } 77 finally{ 78 lock1.unlock(); 79 } 80 81 } 82 } 83 } 84 85 private static class CreateThread3 implements Runnable{ 86 public void run() 87 { 88 for(int i=0;i<5;i++) 89 { try{ 90 lock1.lock(); 91 while(state!=3) 92 { 93 try{ 94 c3.await(); 95 96 } 97 catch(InterruptedException e) 98 { 99 e.printStackTrace(); 100 } 101 } 102 for(int j=0;j<5;j++) 103 { 104 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 105 } 106 System.out.println(); 107 state=1; 108 c1.signal(); 109 110 } 111 finally{ 112 lock1.unlock(); 113 } 114 115 } 116 } 117 } 118 public static void main(String[] args) { 119 // TODO Auto-generated method stub 120 121 122 Thread T1=new Thread (new CreateThread1()); 123 T1.start(); 124 125 Thread T2=new Thread(new CreateThread2()); 126 T2.start(); 127 128 Thread T3=new Thread(new CreateThread3()); 129 T3.start(); 130 131 } 132 133 }
同样采用对public void run 方法的重载,这样就在各自的线程中调用各自run方法,避免了使用一个共同run方法的尴尬
1 package JavaLockPackage; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 //三个线程轮换打印12345 678910,。。。。。有序的打印直到75 7 public class LockAndConditionExam { 8 private static int n=1; 9 private static int state=1; 10 11 private static ReentrantLock lock1=new ReentrantLock(); 12 //获取其中的三个分支线程 13 private static Condition c1=lock1.newCondition(); 14 private static Condition c2=lock1.newCondition(); 15 private static Condition c3=lock1.newCondition(); 16 //的是一个实例,必须要加上static关键字,不然会成为class类, 17 private static class CreateThread1 implements Runnable{ 18 public void run() 19 { 20 for(int i=0;i<5;i++) 21 { try{ 22 lock1.lock(); 23 while(state!=1) 24 { 25 try{ 26 c1.await(); 27 28 } 29 catch(InterruptedException e) 30 { 31 e.printStackTrace(); 32 } 33 } 34 for(int j=0;j<5;j++) 35 { 36 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 37 } 38 System.out.println(); 39 state=2; 40 c2.signal(); 41 42 } 43 finally{ 44 lock1.unlock(); 45 } 46 47 } 48 } 49 } 50 51 private static class CreateThread2 implements Runnable{ 52 public void run() 53 { 54 for(int i=0;i<5;i++) 55 { try{ 56 lock1.lock(); 57 while(state!=2) 58 { 59 try{ 60 c2.await(); 61 62 } 63 catch(InterruptedException e) 64 { 65 e.printStackTrace(); 66 } 67 } 68 for(int j=0;j<5;j++) 69 { 70 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 71 } 72 System.out.println(); 73 state=3; 74 c3.signal(); 75 76 } 77 finally{ 78 lock1.unlock(); 79 } 80 81 } 82 } 83 } 84 85 private static class CreateThread3 implements Runnable{ 86 public void run() 87 { 88 for(int i=0;i<5;i++) 89 { try{ 90 lock1.lock(); 91 while(state!=3) 92 { 93 try{ 94 c3.await(); 95 96 } 97 catch(InterruptedException e) 98 { 99 e.printStackTrace(); 100 } 101 } 102 for(int j=0;j<5;j++) 103 { 104 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 105 } 106 System.out.println(); 107 state=1; 108 c1.signal(); 109 110 } 111 finally{ 112 lock1.unlock(); 113 } 114 115 } 116 } 117 } 118 public static void main(String[] args) { 119 // TODO Auto-generated method stub 120 121 //对run方法进行重载 122 Thread T1=new Thread (){ 123 124 public void run() 125 { 126 for(int i=0;i<5;i++) 127 { try{ 128 lock1.lock(); 129 while(state!=1) 130 { 131 try{ 132 c1.await(); 133 134 } 135 catch(InterruptedException e) 136 { 137 e.printStackTrace(); 138 } 139 } 140 for(int j=0;j<5;j++) 141 { 142 System.out.println(Thread.currentThread().getName()+"-线程--"+n++); 143 } 144 System.out.println(); 145 state=2; 146 c2.signal(); 147 148 } 149 finally{ 150 lock1.unlock(); 151 } 152 153 } 154 } 155 }; 156 T1.start(); 157 158 Thread T2=new Thread(new CreateThread2()); 159 T2.start();//方法是进行new Runnable 实例 160 161 Thread T3=new Thread(new CreateThread3()); 162 T3.start(); 163 164 } 165 166 }