同步代码块实现生产者消费者模式
class Person {
private String name;
private String sex;
private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空 //生产
public void set(String name, String sex) {
synchronized (this) {
// if(isEmpty)
while (!isEmpty.equals(Boolean.TRUE)) {
// 区域不为空,此时生产者应该停下来,等着消费者消费
try {this.wait();// 等待 消费者消费} catch (InterruptedException e) {}
}
this.name = name;
try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace();}
this.sex = sex;
// 生产者生产之后,应该修改存储区域的状态
isEmpty = Boolean.FALSE;// 不为空
this.notifyAll();// 唤醒消费者,起来吃东西了
}
} //消费
public void get() {
synchronized (this) {
// 存储区域为空
while (!isEmpty.equals(Boolean.FALSE)) {
try {this.wait();// 等着生产者去生产} catch (InterruptedException e) {}
}
String name = getName();
String sex = getSex();
System.out.println(name + " --> " + sex);
// 消费完成,应该修改存储区域的状态
isEmpty = Boolean.TRUE;// 空了
this.notifyAll();// 唤醒生产者,
}
}
getter/setter
} //生产者
class Producer implements Runnable {
private Person p;
public Producer(Person p) {
this.p = p;
} public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
p.set("春哥哥", "男");
} else {
p.set("著姐", "女");
}
}
}
}
//消费者
class Consumer implements Runnable {
private Person p;
public Consumer(Person p) {
this.p = p;
}
public void run() {
for (int i = 0; i < 100; i++) {
p.get();
}
}
} public class Producer_ConsumerDemo {
public static void main(String[] args) {
Person p = new Person();
new Thread(new Producer(p)).start();
new Thread(new Consumer(p)).start();
new Thread(new Producer(p)).start();
new Thread(new Consumer(p)).start();
}
}
同步方法实现生产者消费者模式
class Person {
private String name;
private String sex;
private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空
//生产
public synchronized void set(String name, String sex) {
// if(isEmpty)
while (!isEmpty.equals(Boolean.TRUE)) {
// 区域不为空,此时生产者应该停下来,等着消费者消费
try {this.wait();// 等待 消费者消费} catch (InterruptedException e) {}
}
this.name = name;
try {Thread.sleep(1); } catch (InterruptedException e) {}
this.sex = sex;
// 生产者生产之后,应该修改存储区域的状态
isEmpty = Boolean.FALSE;// 不为空
this.notifyAll();// 唤醒消费者,起来吃东西了
} //消费
public synchronized void get() {
// 存储区域为空
while (!isEmpty.equals(Boolean.FALSE)) {
try {this.wait();// 等着生产者去生产} catch (InterruptedException e) {}
}
String name = getName();
String sex = getSex();
System.out.println(name + " --> " + sex);
// 消费完成,应该修改存储区域的状态
isEmpty = Boolean.TRUE;// 空了
this.notifyAll();// 唤醒生产者,
}
getter/setter
} //生产者
class Producer implements Runnable {
private Person p;
public Producer(Person p) {
this.p = p;
}
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
p.set("春哥哥", "男");
} else {
p.set("著姐", "女");
}
}
}
} class Consumer implements Runnable {
private Person p;
public Consumer(Person p) {
this.p = p;
}
public void run() {
for (int i = 0; i < 100; i++) {
p.get();
}
}
}
public class Producer_ConsumerDemo {
public static void main(String[] args) {
Person p = new Person();
new Thread(new Producer(p)).start();
new Thread(new Consumer(p)).start();
new Thread(new Producer(p)).start();
new Thread(new Consumer(p)).start();
}
}
可重入锁实现生产者消费者模式
jkd1.5后的另一种同步机制:通过显示定义同步锁对象来实现同步,这种机制,同步锁应该使用Lock对象充当;
在实现线程安全控制中,通常使用ReentrantLock(可重入锁)。使用该对象可以显示地加锁和解锁;
具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
格式:
public class X {
private final ReentrantLock lock = new ReentrantLock();
//定义需要保证线程安全的方法
public void m(){
lock.lock();//加锁
try{
//... method body
}finally{
lock.unlock();//在finally释放锁
}
}
}
可重入锁没有同步监听对象,咋办呢?
Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
class Person {
private final ReentrantLock lock = new ReentrantLock();// 创建可重入锁对象
private final Condition con = lock.newCondition(); private String name; private String sex;
private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空 //生产
public void set(String name, String sex) {
lock.lock();
while(!isEmpty.equals(Boolean.TRUE)){ //表示不空状态
try {con.await();} catch (InterruptedException e) {}}
try {
this.name = name;
Thread.sleep(1);
this.sex = sex;
isEmpty = Boolean.FALSE;
con.signal();
} catch (InterruptedException e) {} finally {
lock.unlock();
}
} //消费
public void get() {
lock.lock();
while(!isEmpty.equals(Boolean.FALSE)){ //存储区域为空,消费者应该等着
try {
con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
String name = getName();
String sex = getSex();
System.out.println(name + " --> " + sex);
//
isEmpty = Boolean.TRUE;
con.signal();
} finally {
lock.unlock();
} }
getter/setter
} //生产者
class Producer implements Runnable {
private Person p;
public Producer(Person p) {
this.p = p;
} public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
p.set("春哥哥", "男");
} else {
p.set("著姐", "女");
}
}
}
} class Consumer implements Runnable {
private Person p;
public Consumer(Person p) {
this.p = p;
}
public void run() {
for (int i = 0; i < 100; i++) {
p.get();
}
}
} public class Producer_ConsumerDemo {
public static void main(String[] args) {
Person p = new Person();
new Thread(new Producer(p)).start();
new Thread(new Consumer(p)).start();
}
}
同步代码块方式改写卖票程序
class MyRunnable implements Runnable {
private Integer num = 50;
public void run() {
for (int i = 0; i < 200; i++) {
sale();
}
}
private Object o = new Object(); public void sale() {
// synchronized (this) {
// synchronized (MyRunnable.class) {
synchronized (o) {
if (num > 0) {
try {Thread.sleep(1); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + "卖出第"
+ num-- + "张");
}
}
}
} public class TicketDemoSyncByBlock {
public static void main(String[] args) {
Runnable target = new MyRunnable();
new Thread(target, "A").start();
new Thread(target, "B").start();
new Thread(target, "C").start();
}
}
实现Runnable接口的方式,使用同步代码块的方式进行同步。
可以取的同步监听对象为:this、当前方法所在类的Class对象、任一不变对象;
同步方法方式改写卖票程序
class MyRunnable implements Runnable {
private Integer num = 50;
public void run() {
for (int i = 0; i < 200; i++) {
sale();
}
} synchronized public void sale() {
if (num > 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖出第" + num-- + "张");
}
}
} public class TicketDemoSyncByMethod {
public static void main(String[] args) {
Runnable target = new MyRunnable();
new Thread(target, "A").start();
new Thread(target, "B").start();
new Thread(target, "C").start();
}
}
可重入锁方式改写卖票程序
class MyRunnable implements Runnable { private final ReentrantLock lock = new ReentrantLock();
private Integer num = 50; public void run() {
for (int i = 0; i < 200; i++) {
sale();
}
} public void sale() {
lock.lock();
try {
if (num > 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖出第"
+ num-- + "张");
}
} finally {
lock.unlock();
}
}
} public class TicketDemoSyncByReentrantLock {
public static void main(String[] args) {
Runnable target = new MyRunnable();
new Thread(target, "A").start();
new Thread(target, "B").start();
new Thread(target, "C").start();
}
}