线程间通信概述
线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。
模拟场景---两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求用线程间通信
synchronized 方案
//创建资源类,定义属性和操作方法
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();
}
}
Lock 方案
//第一步,创建资源类,定义属性和操作方法
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();
}
}