多线程(线程间通信问题)_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 多线程(线程间通信问题)

多线程(线程间通信问题)

 2015/3/30 0:41:42  高军威  程序员俱乐部  我要评论(0)
  • 摘要:代码1线程不安全:/***线程间通信*其实就是多线程在操作同一个资源*但是操作的动作不同**/classRes{Stringname;Stringsex;}classInputimplementsRunnable{privateResres;Input(Resres){this.res=res;}@Overridepublicvoidrun(){intx=0;while(true){if(x==0){res.name="mike";res.sex="man";}else{res
  • 标签:
代码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() 方法。
  • 相关文章
发表评论
用户名: 匿名