一、线程通信--示例
需求:
input 设置resource , resource为name和sex,output输出resource
代码:
package com.lee.juc.comm;
public class ResourceDemo_01 {
public static void main(String[] args) {
Resource_01 r = new Resource_01();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//资源
class Resource_01{
public String name;
public String sex;
}
//生产者
class Input implements Runnable{
Resource_01 r;
public Input(Resource_01 r) {
this.r = r;
}
public void run() {
int x = 0 ;
while(true) {
if(x==0) {
r.name = "lee";
r.sex = "male";
}else {
r.name = "迪";
r.sex = "女";
}
x = (x+1)%2;
}
}
}
//消费者
class Output implements Runnable{
Resource_01 r;
public Output(Resource_01 r) {
this.r = r;
}
public void run() {
while(true) {
System.out.println(r.name+"...."+r.sex);
}
}
}
结果:
原因:input 设置了lee male后 又设置了name = 迪,sex还没有设置,output就输出了。
解决方法:input和output用同一个锁,只有输入完成后output才能输出,
output输出完成后,input才能输入
解决代码:
扫描二维码关注公众号,回复:
889449 查看本文章
package com.lee.juc.comm;
public class ResourceDemo_01 {
public static void main(String[] args) {
Resource_01 r = new Resource_01();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//资源
class Resource_01{
public String name;
public String sex;
}
//生产者
class Input implements Runnable{
Resource_01 r;
public Input(Resource_01 r) {
this.r = r;
}
public void run() {
int x = 0 ;
while(true) {
synchronized (r) {
if(x==0) {
r.name = "lee";
r.sex = "male";
}else {
r.name = "迪";
r.sex = "女";
}
x = (x+1)%2;
}
}
}
}
//消费者
class Output implements Runnable{
Resource_01 r;
public Output(Resource_01 r) {
this.r = r;
}
public void run() {
while(true) {
synchronized (r) {
System.out.println(r.name+"...."+r.sex);
}
}
}
}
结果:
问题: input了一个资源,却output多个。
二、线程通信--等待唤醒
1、这些方法都是Object的方法:
wait 让线程处于冻结状态,被wait的线程会被存储在线程池中
notify 唤醒线程池中任意一个线程
notifyAll 唤醒线程池中的所有线程
2、代码
package com.lee.juc.comm;
public class ResourceDemo_02 {
public static void main(String[] args) {
Resource_02 r = new Resource_02();
Input_02 in = new Input_02(r);
Output_02 out = new Output_02(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//资源
class Resource_02{
public String name;
public String sex;
public boolean flag = false;//没有定义name和sex
}
//生产者
class Input_02 implements Runnable{
Resource_02 r;
public Input_02(Resource_02 r) {
this.r = r;
}
public void run() {
int x = 0 ;
while(true) {
synchronized (r) {
if(r.flag==true) {
try {r.wait();} catch (InterruptedException e) {e.printStackTrace();}
}else {
if(x==0) {
r.name = "lee";
r.sex = "male";
}else {
r.name = "迪";
r.sex = "女";
}
x = (x+1)%2;
r.flag=true;
r.notify();
}
}
}
}
}
//消费者
class Output_02 implements Runnable{
Resource_02 r;
public Output_02(Resource_02 r) {
this.r = r;
}
public void run() {
while(true) {
synchronized (r) {
if(r.flag==false) {
try {r.wait();} catch (InterruptedException e) {e.printStackTrace();}
}else {
System.out.println(r.name+"...."+r.sex);
r.flag=false;
r.notify();
}
}
}
}
}
3、结果:
3、代码优化
package com.lee.juc.comm;
public class ResourceDemo_03 {
public static void main(String[] args) {
Resource_03 r = new Resource_03();
Input_03 in = new Input_03(r);
Output_03 out = new Output_03(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//资源
class Resource_03{
private String name;
private String sex;
private boolean flag = false;//没有定义name和sex
public synchronized void set(String name,String sex) {
if(flag)
try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
this.name = name;
this.sex = sex;
flag=true;
this.notify();
}
public synchronized void out() {
if(!flag)
try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(name+"...+++..."+sex);
flag=false;
notify();
}
}
//生产者
class Input_03 implements Runnable{
Resource_03 r;
public Input_03(Resource_03 r) {
this.r = r;
}
public void run() {
int x = 0 ;
while(true) {
if(x==0) {
r.set("lee", "male");
}else {
r.set("迪", "女");
}
x = (x+1)%2;
}
}
}
//消费者
class Output_03 implements Runnable{
Resource_03 r;
public Output_03(Resource_03 r) {
this.r = r;
}
public void run() {
while(true) {
r.out();
}
}
}
三、线程通信--多生产者、多消费者
1、流程图
2、代码
package com.lee.juc.comm;
public class ProducerConsumerDemo_01 {
public static void main(String[] args) {
Resource_01 r = new Resource_01();
Producer_01 pro = new Producer_01(r);
Consumer_01 con = new Consumer_01(r);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
class Resource_01{
private String name;
private Integer count=1;
private boolean flag = false;
public synchronized void set(String name) {
while(flag)//================
try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
this.name = name+""+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
this.flag=true;
this.notifyAll();//===============
}
public synchronized void out() {
while(!flag)//=============
try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
this.flag=false;
this.notifyAll();//===================
}
}
class Producer_01 implements Runnable{
Resource_01 r;
public Producer_01(Resource_01 r) {
this.r = r;
}
public void run() {
while(true) {
r.set("烤鸭");
}
}
}
class Consumer_01 implements Runnable{
Resource_01 r;
public Consumer_01(Resource_01 r) {
this.r = r;
}
public void run() {
while(true) {
r.out();
}
}
}
2、结果
四、Lock和Condition
1、Lock
实现提供了比使用 synchronized
方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition
对象。
简单的说Lock即是对synchronized的拓展。
2、Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用。
代码:
package com.lee.juc.comm;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args) {
Resource_05 r = new Resource_05();
Producer_02 pro = new Producer_02(r);
Consumer_02 con = new Consumer_02(r);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
class Resource_05{
private String name;
private Integer count=1;
private boolean flag = false;
Lock lock = new ReentrantLock();
Condition producter_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name) {
lock.lock();
try {
while(flag)
try {producter_con.await();} catch (InterruptedException e) {e.printStackTrace();}
this.name = name+""+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
this.flag=true;
consumer_con.signal();
} finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while(!flag)
try {consumer_con.await();} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
this.flag=false;
producter_con.signal();
} finally {
lock.unlock();
}
}
}
class Producer_02 implements Runnable{
Resource_05 r;
public Producer_02(Resource_05 r) {
this.r = r;
}
public void run() {
while(true) {
r.set("烤鸭");
}
}
}
class Consumer_02 implements Runnable{
Resource_05 r;
public Consumer_02(Resource_05 r) {
this.r = r;
}
public void run() {
while(true) {
r.out();
}
}
}