线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。
模拟场景---两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求用线程间通信
//创建资源类,定义属性和操作方法 class Share{ private int number = 0; //+1方法 public synchronized void incr() throws InterruptedException { //二、判断 操作和通知 while (number != 0) this.wait();//判断number值是否为0 //如果number值为0 number++; System.out.println(Thread.currentThread().getName()+"::"+number); //通知其他线程 this.notifyAll(); } //-1方法 public synchronized void decr() throws InterruptedException { //判断 while (number != 1) this.wait(); //操作 number--; System.out.println(Thread.currentThread().getName()+"::"+number); //通知其他线程 this.notifyAll(); } } public class ThreadDemo1 { //创建多个线程,调用资源类的操作方法 public static void main(String[] args) { Share share = new Share(); //创建线程 new Thread(()->{ for (int i = 1;i <= 10;i++){ try { share.incr(); //进行10次+1操作 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程一").start(); new Thread(()->{ for (int i = 1;i <= 10;i++){ try { share.decr(); //进行10次-1操作 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程二").start(); } }
//第一步,创建资源类,定义属性和操作方法 class Share{ private int number = 0; //创建lock private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); //+1 public void incr() throws InterruptedException { //上锁 lock.lock(); try { //判断 while (number != 0) condition.await(); //操作 number++; System.out.println(Thread.currentThread().getName()+"::"+number); //通知 condition.signalAll(); }finally { //解锁 lock.unlock(); } } //-1 public void decr() throws InterruptedException { //上锁 lock.lock(); try { //判断 while (number !=1) condition.await(); //操作 number--; System.out.println(Thread.currentThread().getName()+"::"+number); //通知 condition.signalAll(); }finally { //解锁 lock.unlock(); } } } public class ThreadDemo2 { public static void main(String[] args) { Share share = new Share(); //创建多个线程 new Thread(()->{ for (int i=1;i<=10;i++){ try { share.incr();//进行10次+1操作 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程一").start(); new Thread(()->{ for (int i=1;i<=10;i++){ try { share.decr();//进行10次-1操作 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程二").start(); } }
案例:线程一打印 5 次,线程二打印 10 次,线程三打印 15 次 ,按照此顺序循环 10 轮
//创建资源类,定义属性和操作方法 class ShareResource{ //定义标志位 private int flag = 1; //创建Lock锁 private Lock lock = new ReentrantLock(); //创建三个condition private Condition c1 = lock.newCondition(); private Condition c2 = lock.newCondition(); private Condition c3 = lock.newCondition(); //打印5次,参数 第几轮 public void print5(int loop) throws InterruptedException { //上锁 lock.lock(); try { //判断 while (flag != 1){ c1.await(); } //操作 打印5次 for (int i = 1;i <= 5;i++) System.out.println(Thread.currentThread().getName()+"::"+i+":轮数"+loop); //通知 先修改标志位为2 再通知第二个线程 flag = 2; c2.signal(); }finally { lock.unlock(); } } public void print10(int loop) throws InterruptedException { //上锁 lock.lock(); try { //判断 while (flag !=2){ c2.await(); } //操作 打印10次 for (int i = 1; i <= 10; i++) System.out.println(Thread.currentThread().getName()+"::"+i+":轮数"+loop); flag = 3; //通知 c3.signal(); }finally { lock.unlock(); } } public void print15(int loop) throws InterruptedException { //上锁 lock.lock(); try { //判断 while (flag != 3){ c3.await(); } //操作 打印15次 for (int i = 1; i <= 15; i++) System.out.println(Thread.currentThread().getName()+"::"+i+":轮数"+loop); flag = 1; //通知 c1.signal(); }finally { lock.unlock(); } } } public class ThreadDemo3 { public static void main(String[] args) { ShareResource shareResource = new ShareResource(); new Thread(()->{ for (int i = 1; i <= 10; i++) { try { shareResource.print5(i); //调用打印5次的方法 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程一").start(); new Thread(()->{ for (int i = 1; i <= 10; i++) { try { shareResource.print10(i); //调用打印10次的方法 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程二").start(); new Thread(()->{ for (int i = 1; i <= 10; i++) { try { shareResource.print15(i);//调用打印15次的方法 } catch (InterruptedException e) { e.printStackTrace(); } } },"线程三").start(); } }