代码1
线程不安全:
class="java" name="code">
/**
* 线程间通信
* 其实就是多线程在操作同一个资源
* 但是操作的动作不同
* */
class Res
{
String name;
String sex;
}
class Input implements Runnable
{
private Res res;
Input(Res res)
{
this.res =res;
}
@Override
public void run() {
int x=0;
while (true) {
if(x==0)
{
res.name = "mike";
res.sex = "man";
}
else
{
res.name = "丽丽";
res.sex = "女女女女女";
}
x = (x+1)%2;
}
}
}
class Output implements Runnable
{
private Res res;
Output(Res res)
{
this.res =res;
}
@Override
public void run() {
while (true) {
System.out.println(res.name+"......"+res.sex);
}
}
}
class Test
{
public static void main(String[] args) {
Res res = new Res();
Input i = new Input(res);
Output o = new Output(res);
Thread t1 = new Thread(i);
Thread t2 = new Thread(o);
t1.start();
t2.start();
}
}
运行结果:
线程不安全
代码2
线程安全:
class Res
{
String name;
String sex;
}
class Input implements Runnable
{
private Res res;
Input(Res res)
{
this.res =res;
}
@Override
public void run() {
int x=0;
while (true) {
synchronized (res) {
if(x==0)
{
res.name = "mike";
res.sex = "man";
}
else
{
res.name = "丽丽";
res.sex = "女女女女女";
}
x = (x+1)%2;
}
}
}
}
class Output implements Runnable
{
private Res res;
Output(Res res)
{
this.res =res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
System.out.println(res.name+"......"+res.sex);
}
}
}
}
class Test
{
public static void main(String[] args) {
Res res = new Res();
Input i = new Input(res);
Output o = new Output(res);
Thread t1 = new Thread(i);
Thread t2 = new Thread(o);
t1.start();
t2.start();
}
}
运行结果:
多线程安全;
需求:放入一个值输出一个值;(多线程通讯:等待唤醒机制)
代码3:
/**
* 线程间通信
* 其实就是多线程在操作同一个资源
* 但是操作的动作不同
*
* wait();
* notify();
* notifyAll();
*
* 都使用在同步中,因为要对持有监视器(锁)的线程操作。
* 所以要使用在同步中,应为只有同步才具有锁。
*
* 为什么这些操作线程的方法要定义Object类中呢?
* 因为这些方法在操作同步中线程时,都必须要标识他们做操作线程只有的锁。
* 只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒。
* 不可以对不同锁中的线程进行唤醒。
*
* 也就是说,等待和唤醒必须是同一个锁。
*
*而锁可以是任意对象,所以可以任意对象调用的方法定义在Object类中。
* */
class Res
{
String name;
String sex;
boolean flag=false;
}
class Input implements Runnable
{
private Res res;
Input(Res res)
{
this.res =res;
}
@Override
public void run() {
int x=0;
while (true) {
synchronized (res) {
if(res.flag)
{
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(x==0)
{
res.name = "mike";
res.sex = "man";
}
else
{
res.name = "丽丽";
res.sex = "女女女女女";
}
x = (x+1)%2;
res.flag=true;
res.notify();
}
}
}
}
class Output implements Runnable
{
private Res res;
Output(Res res)
{
this.res =res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.name+"......"+res.sex);
res.flag = false;
res.notify();
}
}
}
}
class Test
{
public static void main(String[] args) {
Res res = new Res();
Input i = new Input(res);
Output o = new Output(res);
Thread t1 = new Thread(i);
Thread t2 = new Thread(o);
t1.start();
t2.start();
}
}
运行结果:
符合需求;
以上代码优化:
代码4:
class Res
{
private String name;
private String sex;
private boolean flag=false;
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(this.name+"......"+this.sex);
flag = false;
this.notify();
}
}
class Input implements Runnable
{
private Res res;
Input(Res res)
{
this.res =res;
}
@Override
public void run() {
int x=0;
while (true) {
if(x==0)
res.set("mike", "man");
else
res.set("丽丽", "女女女女女");
x = (x+1)%2;
}
}
}
class Output implements Runnable
{
private Res res;
Output(Res res)
{
this.res =res;
}
public void run() {
while (true) {
res.out();
}
}
}
class Test
{
public static void main(String[] args) {
Res res = new Res();
new Thread(new Input(res)).start();
new Thread(new Output(res)).start();
}
}
生产消费模式:
多个生产者,多个
消费者:
代码5:
/**
* 资源
* */
class Resource
{
private String name;
private int count=1;
private boolean flag = false;
public synchronized void set(String name) {
while(flag)
{
try {wait();//放弃执行权 注意:当被唤醒后,获得执行权接着往下执行,并持有共同锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
notify();
}
public synchronized void out() {
while(!flag)
{
try {wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
notify();
}
}
/**
* 生产者
* */
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
res.set("+商品+");
}
}
}
/**
* 消费者
* */
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
res.out();
}
}
}
/**
* 测试
* */
class Test
{
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
没有反应了,原因是 这几个线程都放弃执行权了;
解决以上问题:
将notify()方法,修改为notifyAll()(比较通用的方式);
运行结果图:
运行结果OK了;
问题1:但是 notifyAll唤醒了所有线程包括本方的线程,要怎样使生产者线程运行完唤醒消费者线程而不是全都唤醒?
用Lock来替代sysynchronized :
代码4使用lock实现方式:
代码6使用lock实现多线程 生产消费模式 一对一:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 资源
* */
class Resource
{
private String name;
private int count=1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void set(String name) throws InterruptedException {
lock.lock();
try
{
while(flag)
{
condition.await();
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition.signal();//唤醒 下一个线程
}
finally
{
lock.unlock();//释放资源
}
}
public void out() throws InterruptedException {
lock.lock();
try
{
while(!flag)
condition.await();
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
condition.signal();//唤醒 下一个线程
}
finally
{
lock.unlock();//释放资源
}
}
}
/**
* 生产者
* */
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.set("+商品+");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
* */
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.out();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 测试
* */
class Test
{
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t4.start();
}
}
代码5的修改版使用lock实现方式:
代码7使用lock实现多线程生产消费模式 多对多:
代码7:
/**
* 资源
* */
class Resource
{
private String name;
private int count=1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void set(String name) throws InterruptedException {
lock.lock();
try
{
while(flag)
condition.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition.signalAll();//唤醒所有使用共享对象的线程
}
finally
{
lock.unlock();//释放资源
}
}
public void out() throws InterruptedException {
lock.lock();
try
{
while(!flag)
condition.await();
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
condition.signalAll();
}
finally
{
lock.unlock();//释放资源
}
}
}
/**
* 生产者
* */
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.set("+商品+");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
* */
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.out();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 测试
* */
class Test
{
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);t1.start();
Thread t3 = new Thread(con);t3.start();
Thread t2 = new Thread(pro);t2.start();
Thread t4 = new Thread(con);t4.start();
}
}
现在使用lock 的新特性解决代码5中的问题1;
一个lock上可以有多个condition :
代码8:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 资源
* JDK1.5 中提供了多线程升级解决方案
* 将synchronized替换成Condition对象。
* 将Object中的wait,notify,nottfyAll,替换了Condition对象。
* 该对象可以使用Lock锁进行获取。
* 该示例中,实现了本方只唤醒对方的操作。
* */
class Resource
{
private String name;
private int count=1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();//锁条件
private Condition condition_con = lock.newCondition();//
public void set(String name) throws InterruptedException {
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();//唤醒某个线程
}
Finally
{
lock.unlock();//释放资源 一定要执行
}
}
public void out() throws InterruptedException {
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();//释放资源
}
}
}
/**
* 生产者
* */
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.set("+商品+");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
* */
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run() {
while (true) {
try {
res.out();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 测试
* */
class Test
{
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);t1.start();
Thread t3 = new Thread(con);t3.start();
Thread t2 = new Thread(pro);t2.start();
Thread t4 = new Thread(con);t4.start();
}
}
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样。
Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。