java多线程编程方面的一些认识_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java多线程编程方面的一些认识

java多线程编程方面的一些认识

 2012/4/23 12:40:11  独爱Java  程序员俱乐部  我要评论(0)
  • 摘要:1、线程入门//构建线程类——方式一,继承Thread类方式。importjava.util.Date;publicclassThreadDemo{//main方法,程序的入口publicstaticvoidmain(String[]args){//定义并实例化外部类对象ThreadDemotd=newThreadDemo();//通过外部类对象来实例化内部类对象PrintThreadpt1=td.newPrintThread("thread1",1000);PrintThreadpt2=td
  • 标签:认识 多线程 Java 编程 线程
1、线程入门

//构建线程类——方式一,继承Thread类方式。
import java.util.Date;

public class ThreadDemo{
	//main方法,程序的入口
	public static void main(String[] args){
		//定义并实例化外部类对象
		ThreadDemo td = new ThreadDemo();
		//通过外部类对象来实例化内部类对象
		PrintThread pt1 = td.new PrintThread("thread1",1000);
		PrintThread pt2 = td.new PrintThread("thread2",3000);
		//启动线程1,线程2
		pt1.start();
		pt2.start();
		//通过调用start方法,start方法会去调用run方法启动线程
	}
	//定义线程类,内部类
	class PrintThread extends Thread{
		public PrintThread(String name,long sleepTime){
			this.name = name;
			this.sleepTime = sleepTime;
		}
		//覆写父类的run方法
		@Override
		public void run(){
			//简单模拟循环
			while(true){
				try{
					//定义并实例化对象
					Date date = new Date();
					System.out.println("name = "+name+",date = "+date.toString());
					//线程休眠
					Thread.sleep(sleepTime);
				}catch(Exception e){
					//出现异常
					System.out.println(e);
				}
			}
			

		}
		//线程名称、休眠时间
		private String name;
		private long sleepTime;
	}
}
//这种方式构建线程缺点:java的单继承是个问题。

//构建线程类——方式二,通过实现Runnable接口
import java.util.Date;

public class PrintDemo2{
	public static void main(String[] args){
		PrintThread pt1 = new PrintThread();
		PrintThread pt2 = new PrintThread();
		//实例化线程对象传入Runnable接口实现,并启动线程。
		new Thread(pt1).start(); 
		new Thread(pt2).start();
		//启动start方法后会去执行run方法
	}
	//通过实现Runnable接口来定义线程类
	static class PrintThread implements Runnable{
		public PrintThread(String name,long sleepTime){
			this._name = name;
			this._sleepTime = sleepTime;
		}
		public void run(){
			while(true){
				try{
					Date date = new Date();
					System.out.println("name = "+_name+",date = "+date);
					//线程休眠
					Thread.sleep(_sleepTime);
				}catch(Exception e){
					System.out.println(e);
				}
			}
		}
		//定义线程名称、休眠时间
		private String _name;
		private long _sleepTime;
	}
}

2、线程同步入门

//有问题,待定解决了。
//银行账户并发程序演示
public class BankSynDemo{
	
	//main方法,程序的入口
	public static void main(String[] args) throws Exception{
		Account[] accounts = new Account[10];

		//初始化10个账户对象,金额设置为100f
		//totalMoney = 1000f
		for(int i=0;i<10;i++){
			accounts[i] = new Account("account_"+i,100f);
		}
		
		//随机产生一个转账金额数目
		Random random = new Random();
		float transMoney = 0f;

		//构建1000个线程
		for(int j=0;j<1000;j++){
			transMoney = random.nextFloat();
			//编写代码如果写成下面这种方式
			//循环一千次,多构建了二千个对象,而达到的效果是一样的。
			//Random random = new Random();
			//float transMoney = random.nextFloat();
			new Thread(new BankTransThread(accounts,transMoney)).start();
		}

		//查看余额是否正确,在主线程中查看
		//main thread.
		while(true){
			float sum = 0f;
			for(int k=0;k<accounts.length;k++){
				sum += accounts[k].get_amount();
			}
			//total money print.
			System.out.println("totalMoney = "+sum+"f,thread = "+Thread.currentThread().getName());
		}
		
	}

	//定义银行账户实例类
	static class Account{
		//构造方法
		public Account(String accountName,float amount){
			this._name = accountName;
			this._amount = amount;
		}
		
		//转入金额,不进行同步处理。
		public void income(float addAmount){
			if(addAmount>0f){
				//进行转入处理
				this._amount += addAmount;
				System.out.println("add success,addAmount = "+addAmount+",thread = "+Thread.currentThread().getName());
			}else{
				//转入失败显示,一般采用记录日志方式
				//添加金额不满足条件,不进行阻塞,直接不进行操作即可。
				System.out.println("add error,addAmount = "+addAmount+",thread = "+Thread.currentThread().getName());
			}
		}

		//转出金额,进行同步处理
		public void expend(Account toAccount,float transMoney){
			synchronized(Account.class){
				//Date date = new Date();
				//账户金额变更处理
				if(transMoney>0f && this._amount>transMoney){
					this._amount -= transMoney; //当前账户减少金额
					toAccount.income(transMoney); //转入账户添加金额
					System.out.println("expend success,toAccount = "+toAccount.get_name()+",transMoney = "+transMoney+",thread = "+Thread.currentThread().getName());
				}else{
					//转出失败,一般采用记录日志方式
					System.out.println("expend error,toAccount = "+toAccount.get_name()+",transMoney = "+transMoney+",thread = "+Thread.currentThread().getName());
				}
				//进行唤醒其他所有等待的线程来抢占这个锁对象操作
				//this.notifyAll(); 出异常了
			}
		}

		//获取当前账户金额
		public float getAmountMoney(){
			synchronized(Account.class){
				return this._amount;
			}
		}
		
		//定义账户名称、金额
		private String _name;
		private float _amount;

		public String get_name() {
			return _name;
		}

		public float get_amount() {
			return _amount;
		}

	}

	//定义银行转账线程类
	static class BankTransThread implements Runnable{

		public BankTransThread(Account[] accounts,float transMoney){
			this.accounts = accounts;
			this.transMoney = transMoney;
		}

		public void run(){
			//转账方法调用,简单模拟,一直在进行转账操作
			while(true){
				transMoney(this.transMoney);
			}
			//只转账一次
			//transMoney(this.transMoney);
		}

		//转账方法实现
		protected void transMoney(float transMoney){
			int size = accounts.length;
			//从外部传入处理,不再写死
			//float transMoney = 10f; //转账金额为10f
			Random random = new Random();

			int from = random.nextInt()%size;
			int to = random.nextInt()%size;
			//处理负数情况
			if(from<0) from = -from; //变为正数
			if(to<0) to = -to; //变为正数

			//进行转账处理
			accounts[from].expend(accounts[to],transMoney);
		}
		private Account[] accounts; //银行账户集合
		private float transMoney; //转账金额
	}
}

3、并发模型框架设计

//服务提供者,对外提供服务:它通过一个接口对外提供服务。
//客户端调用方,下面简单代码模拟。
//原文链接:http://www.ibm.com/developerworks/cn/java/l-multithreading/#ibm-pcon
//看得奇怪奇怪的文章,先记录下来。主要代码如下:

//服务接口
public interface Service{
	public void sayHello();
}


//服务接口实现
public class ServiceImpl implements Service{
	public void sayHello(){
		System.out.println("hello world.");
	}
}


//存在问题:线程并发问题。

//同步调用,造成client阻塞。原因是由于所有的服务调用都是同步的。
//解决方案是改成异步调用方式,把服务的调用和服务的执行进行分离。

//下面代码演示使用主动对象来封装并发逻辑。
//应用逻辑和并发逻辑的隔离,服务调用和服务执行的隔离。

//定义MethodRequest接口,用来包装调用者的请求。
public interface MethodRequest{
	public void call();
}


//定义一个ActiveQueue队列,实现看具体业务场景。
public class ActiveQueue{
	private Object lock = new Object(); //锁对象
	private Stack<MethodRequest> activeQueue; //请求栈、队列
	private final static int SIZE = 20; //栈、队列长度

	public ActiveQueue(){
		activeQueue = new Stack<MethodRequest>(); //初始化栈、队列对象
	}

	//请求入栈方法实现
	public void enqueue(MethodRequest request) throws Exception{
		//线程同步处理
		synchronized(lock){
			while(activeQueue.size()>SIZE){
				lock.wait(); //条件判定,进行阻塞。
			}
			//将请求放到栈中。
			activeQueue.push(request);
			lock.notifyAll(); //交出锁对象,让其他线程来抢占这个锁对象。
			System.out.println("request input success,thread = "+Thread.currentThread().getName());
		}
	}

	//获取请求出栈方法实现
	public MethodRequest dequeue() throws Exception{
		synchronized(lock){
			while(activeQueue.empty()){
				lock.wait();
			}
			//将请求退出栈中
			MethodRequest popRequest = activeQueue.pop();
			lock.notifyAll(); //交出锁对象,让其他线程来抢占这个锁对象。
			System.out.println("request pop success,thread = "+Thread.currentThread().getName());
			return popRequest;
		}
	}

}


//定义一个ActiveObject类,用来包装并发逻辑。
public class ActiveObject implements Runnable{
	private ActiveQueue activeQueue; //方法请求队列
	public ActiveObject(){
		activeQueue = new ActiveQueue();
	}
	//将方法请求(request)放到队列中去
	public void enqueue(MethodRequest request){
		this.activeQueue.enqueue(request);
	}
	//提取出当前队列中的请求
	public MethodRequest dequeue(){
		return this.activeQueue.dequeue();
	}
	public void run(){
		while(true){
			//调用获取一个request请求
			MethodRequest request = this.dequeue();
			//处理相关业务逻辑
			request.call();
		}
	}
}


//下面模拟更上一层处理代码

//方法请求的实现类,面向接口编程
public class SayHello implements MethodRequest{
	//构造方法,传入service对象参数
	public SayHello(Service service){
		this.service = service;
	}
	public void call(){
		//调用service的sayHello方法
		this.service.sayHello();
	}
	//引入service对象
	private Service service;
}


//定义一个服务代理类,来完成请求的封装、排队功能。
//当然为了做到对client的透明,该类必须实现service接口。
public class ServiceProxy implements Service{
	public ServiceProxy(){
		//实例化服务实现对象
		this.service = new ServiceImpl();
		//实例化活动对象
		this.activeObject = new ActiveObject();
	}
	public void sayHello(){
		MethodRequest request = new SayHello(this.service);
		this.activeObject.enqueue(request); //加入到请求队列中
	}
	private Service service;
	private ActiveObject activeObject;
}


//客户端类
public class Client{
	//持有业务层service的引用
	private Service service;

	//构造方法,参数为service对象
	public Client(Service service){
		this.service = service;
	}

	//requestService方法实现
	public void requestService(){
		this.service.sayHello();
	}

	//main方法,程序的入口
	public static void main(String[] args){
		Client clientMain = new Client(new ServiceImpl());
		clientMain.sayHello();
	}

}


//并发逻辑下的客户端代码如下:
public class ClientMainDemo{
	public static void main(String[] args){
		Service service = new ServiceProxy();
		//1、实例化一个实现serviceimpl对象。 //为什么不直接实例化呢,要用代理服务对象呢。
		//2、实例化一个活动对象,用来包装了并发逻辑的处理对象。

		Client client = new Client(service);
		client.requestService();//调用方法
	}
}
发表评论
用户名: 匿名