java多线程之类锁

参考文章:http://blog.csdn.net/ymeng_bupt/article/details/6826936

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在java多线程中,如果你在某个类的方法中加了类锁,千万需要注意一个问题:

在唤醒其它线程时,不要用this.notify()或this.notifyAll(),这两个方法用于对象锁,而不是类锁。

---------------------------------------------------------------------------------------------------------------------------------------

开始时,我没有注意以上问题,给方法加了类锁后,直接用this.notifyAll()唤醒其它线程,结果一个

都唤醒不了。加了类锁后,正确的唤醒其它线程的方法是:

类名.class.notifyAll();

如User.class.notifyAll();

-------------------------------------------------------------------------------------------------------------------------------------------------

贴下我加类锁的代码:

/**
	 * 加类锁,类名为QiaoPai
	 */
	public void AddClassLock()
	{
		synchronized(QiaoPai.class)
		{
			try {
				//不满足条件,线程就进入等待状态
				if(!nextOne.equals(Thread.currentThread().getName()))
				{
					QiaoPai.class.notifyAll();//唤醒所有等待的线程
					QiaoPai.class.wait();//进入等待状态
				} 
			} 
			catch (Exception e) {e.printStackTrace();}
		}
	}

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面说下我加类锁的原因和用途。

我打算用4个线程模拟桥牌的打牌过程,第一步当然是显示每个线程拥有的牌啦。

我把桥牌的业务功能封装在了一个类中,该类中就有一个输出牌点的功能。

4个线程就有4个该类的对象,如何让这4个线程在输出牌点时输出结果不混乱呢?

这时我用类锁解决了4个线程输出牌点显示混乱的问题。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

效果截图如下(玩家:北、东、南、西):


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

主要代码如下:

import mythread.MyThread;
import util.Poker;

public class main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Poker.Shuffle();//洗牌
		
		//创建线程
		MyThread threadN=new MyThread();
		MyThread threadE=new MyThread();
		MyThread threadS=new MyThread();
		MyThread threadW=new MyThread();
		
		//发牌
		threadN.setPoker(Poker.getPokerN());
		threadE.setPoker(Poker.getPokerE());
		threadS.setPoker(Poker.getPokerS());
		threadW.setPoker(Poker.getPokerW());
		
		//设置线程名字
		threadN.setName("N");
		threadE.setName("E");
		threadS.setName("S");
		threadW.setName("W");
		
		//启动线程
		threadN.start();
		threadE.start();
		threadS.start();
		threadW.start();
	}

}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

package mythread;
import java.lang.Thread;
import java.util.List;

import business.QiaoPai;

//线程类
public class MyThread extends Thread{

	QiaoPai qiaoPai=new QiaoPai();
	
	public void run()
	{
		try {
			
			qiaoPai.ShowPoker();
		}
		catch (Exception e) {e.printStackTrace();}
	}
	
	//设置扑克牌
	public void setPoker(List<Integer> poker) {
		qiaoPai.setPoker(poker);
	}
	
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

package business;

import java.util.ArrayList;
import java.util.List;

//桥牌业务类
public class QiaoPai {
	List<Integer> poker=new ArrayList<Integer>(new Integer(13));//牌
	public static String nextOne="N";//下一个玩家
	
	//叫牌
	public String JiaoPai(String info)
	{
		String pai="";
		
		return pai;
	}
	
	//获取扑克牌
	public List<Integer> getPoker() {
		return poker;
	}

	//设置扑克牌
	public void setPoker(List<Integer> poker) {
		this.poker = poker;
	}


	//显示扑克牌
	public void ShowPoker()
	{
		synchronized(QiaoPai.class) 
		{
			AddClassLock();
			System.out.print(Thread.currentThread().getName()+":");
			for(int i=0;i<poker.size();i++)
			{
				System.out.print(poker.get(i)+" ");
			}
			System.out.println();
			setNextOne();
			DelClassLock();
		}
	}
	
	
	/**
	 * 加类锁,类名为QiaoPai
	 */
	public void AddClassLock()
	{
		synchronized(QiaoPai.class)
		{
			try {
				//不满足条件,线程就进入等待状态
				if(!nextOne.equals(Thread.currentThread().getName()))
				{
					QiaoPai.class.notifyAll();//唤醒所有等待的线程
					QiaoPai.class.wait();//进入等待状态
				} 
			} 
			catch (Exception e) {e.printStackTrace();}
		}
	}
	
	
	/**
	 * 删除类锁,即唤醒所有等待的线程
	 */
	public void DelClassLock()
	{
		synchronized(QiaoPai.class)
		{
			try{
				QiaoPai.class.notifyAll();
			} 
			catch (Exception e) {e.printStackTrace();}
		}
	}
	

	/**
	 * 设置下一位玩家
	 */
	public static void setNextOne()
	{
		if(nextOne.equals("N"))
		{
			nextOne="E";
		}
		else if(nextOne.equals("E"))
		{
			nextOne="S";
		}
		else if(nextOne.equals("S"))
		{
			nextOne="W";
		}
		else if(nextOne.equals("W"))
		{
			nextOne="N";
		}
		else
		{
			
		}
	}
}

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

您的十分满意是我追求的宗旨。

您的一点建议是我后续的动力。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

friendan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值