Java实现线程间的通讯--使用synchronized关键字和JUC方式实现
即比较经典的生产者和消费者问题,生产者在资源为0时进行生产;在资源不为0时,消费者进行消费,生产者和消费者交替执行。多线程的运行由CPU分配执行的,要交替执行,也就是实现
--
当资源为0时,如果消费者获取执行权,则等待并唤醒生产者生产;如果资源不为0,则消费者消费后,再释放锁唤醒生产者生产。
同样的
当资源不为0时,如果生产者获取执行权,则等待并唤醒消费者进行消费;如果资源为0,则生产者生产后,再释放锁唤醒消费者消费。
使用synchronized关键字实现
技术栈:synchronized + wait() + notifyAll()
实现类
java
//生产者和消费者各实现为一个方法
public class SynchronizedCommunication {
//初始化一个变量,作为操作的同步资源数
private int count;
//生产者操作
public synchronized void add(){
try{
//对共同资源判断,当存在资源
while(count != 0) {
//则生产线程进入等待状态
this.wait();
}
//生产者生产
count++;
//打印一下当前线程及操作的共同资源的值,便于理解
System.out.println(Thread.currentThread().getName()+"::"+count);
}catch (InterruptedException e){
throw new RuntimeException(e);
}finally {
//唤醒消费者消费
this.notifyAll();
}
}
//消费者操作
public synchronized void subtract(){
try{
//对共同资源判断
while (count == 0){
//则消费线程进入等待状态
this.wait();
}
//消费者消费
count--;
System.out.println(Thread.currentThread().getName()+"::"+count);
}catch (InterruptedException e){
throw new RuntimeException(e);
}finally {
//唤醒生产者生产
this.notifyAll();
}
}
}
注意:上述代码中判断使用的时while循环,因为如果实例化的线程不止一个生产者和消费者时,判断不止一次,if()语句来进行判断会出现假醒问题,可能操作的共同资源有负数的情况。所以不管线程是在什么情况下被唤醒,都要进行判断,符合要求再进行生产或是消费的动作。
测试类
java
//这里创建了四个线程,分别两个生产者,两个消费者;可以看一下,如果在这种情况下,使用if语句来进行判断,可能出现假醒问题
public class SynchronizedCommunicationTest {
public static void main(String[] args) {
//实例化共同资源类对象
SynchronizedCommunication sc = new SynchronizedCommunication();
//创建生产者线程,匿名内部类实现操作
Thread t0 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
sc.add();
}
}
},"生产者A");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
sc.subtract();
}
}
},"消费者B");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
sc.add();
}
}
},"生产者C");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
sc.subtract();
}
}
},"消费者D");
t0.start();
t1.start();
t2.start();
t3.start();
}
}
JUC方式实现
技术栈:Lock锁接口 + Condition接口
实现类
java
lock.unlock();
}
}
public void subtract(){
lock.lock();
try {
while (count == 0) {
condition.await();
}
System.out.println(Thread.currentThread().getName()+"---"+(--count));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
condition.signalAll();
lock.unlock();
}
}
}
测试类
java
public class LockCommunicationTest {
public static void main(String[] args) {
LockCommunication lc = new LockCommunication();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lc.add();
}
}
},"生产者1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lc.add();
}
}
},"生产者2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lc.subtract();
}
}
},"消费者1");
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lc.subtract();
}
}
},"消费者2");
t1.start();
t2.start();
t3.start();
t4.start();
}
}