多线程编程中主要分为两种类型,一种是多个线程执行相同的任务,这些任务之间只有互斥的作用力存在,而没有同步的作用力存在。如何来理解互斥和同步的区别呢?说简单点
互斥就是:多个线程之间只有竞争资源的存在,任务之间没有前后顺序的关系。比如说火车上多个乘客共享同一个卫生间,多个乘客之间谁竞争到了资源,谁就去用;而同步指的
是,多个线程之间执行任务有前后制约的关系,比如说两个线程实现售票和买票的场景,那就是买票的线程一定要等售票的线程售出一张票才可以去取出这张票,否则只能等待,
而售票的线程售出一张票后,只能等取出的线程取出当前这张售出的票后才能售下一张票,否则就会出现售票线程连续售出 100 、99、98 三张票,而取票线程只能拿到最后一张
票号为98的票。这种场景应该是要避免de。
我们这里要实现的是同步的应用场景,也就是售一张票买一张票的过程。很明显这里两个线程执行的任务不一样,也就是需要执行的代码不一样。因此这里就可以得出一个简
单的结论:当我们要实现一个同步的应用场景时,常常需要分三步走,1、抽象出协同处理任务的线程 2、抽象出共享的数据 3、在共享数据中处理好同步的逻辑关系。
话不多说直接贴代码:
package audaque.com.pbting.shareData;
/**
* 这里实现使用多线程 来实现数据的共享
* @author Administrator
*
*/
public class MultiThreadShareData {
public static void main(String[] args) {
ShareDate shareDate = new ShareDate(100);
new Thread(new IncrementThread(shareDate)).start();
new Thread(new DecrementThread(shareDate)).start();
}
}
//对共享数据进行增加的线程
class IncrementThread implements Runnable{
private ShareDate shareDate ;
public IncrementThread(ShareDate shareDate) {
super();
this.shareDate = shareDate;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(this.shareDate.getVariable() > 0){
//拿票,票号大于0 才去拿
this.shareDate.increment();
}
}
}
//对共享数据进行递减的线程
class DecrementThread implements Runnable{
private ShareDate shareDate ;
public DecrementThread(ShareDate shareDate) {
super();
this.shareDate = shareDate;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(this.shareDate.getVariable() >0){
this.shareDate.decrement();
}
}
}
//封装需要共享的数据
class ShareDate{
private int variable = 0 ;
private boolean flag = false ;
public ShareDate(int variable) {
super();
this.variable = variable;
}
public int getVariable() {
return variable;
}
public void setVariable(int variable) {
this.variable = variable;
}
public void increment(){
//在这里 处理同步的逻辑
synchronized (ShareDate.class) {
if(flag){//如果为true,则取出刚刚的售出的票
System.out.println("买的票号是====>:"+this.variable);
this.flag = (!this.flag);//将当前的状态取反
//并唤醒买票的线程可以继续买票
ShareDate.class.notify();
}else{//否则的话, 则等待售票的线程进行售票
try {
ShareDate.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//这是卖的操作
public void decrement(){
synchronized (ShareDate.class) {
if(flag){//如果为真,表示等消费者将刚刚卖出的票进行取出
try {
ShareDate.class.wait();
//等客户取出后再去将票号减一
this.variable--;//买票操作
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
this.flag = (!this.flag);
System.out.println("卖出的票号是---->:"+this.variable);
//并唤醒买票的线程
ShareDate.class.notify();
}
}
}
}
运行的结果: