`

JAVA范例 十三)多线程编程(1)

 
阅读更多

第13章 多线程编程

  13.1 多线程的五种基本状态

  实例222 启动线程 

package Chapter17.status;

import java.util.Date;

public class ThreadLife {
	public void startY() {
		ThreadY ty = new ThreadY();// 创建实例
		ty.startThreadY(); // 启动ThreadY线程
		try {
			Thread.sleep(1000); // 当前线程休眠一秒钟
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ty.stopThreadY(); // 停止ThreadY线程
	}

	public void startX() { // 开始第二个
		Runnable runnX = new ThreadX(); // 创建实例
		Thread threadX = new Thread(runnX); // 将实例放入线程中
		threadX.start(); // start方法启动线程
	}

	public static void main(String[] args) { // java程序主入口处
		ThreadLife test = new ThreadLife(); // 实例化对象
		test.startY(); // 调用方法
		test.startX();
	}

}

class ThreadY extends Thread { // 继承java.lang.Thread类定义线程
	private boolean isRunState = false; // 标记线程是否需要运行

	public void start() { // 覆盖了父类的start方法,
		this.isRunState = true; // 将isRunState置为ture,表示线程需要运行
		super.start();
	}

	public void run() {
		int i = 0;
		try {
			while (isRunState) { // 如果isRunState为真,说明线程还可以继续运行
				this.setName("Thread-" + i++);
				System.out.println("线程Y:" + this.getName() + " 正在运行");
				Thread.sleep(200); // sleep方法将当前线程休眠。
			}
		} catch (Exception e) { // 捕获异常
		}

		System.out.println(this.getName() + "运行结束...");
	}

	public void setRunning(boolean isRunState) { // 设置线程
		this.isRunState = isRunState;
	}

	public void startThreadY() { // 启动ThreadY线程
		System.out.println("启动线程Y...");
		this.start();
	}

	public void stopThreadY() { // 停止ThreadY线程
		System.out.println("结束线程Y...");
		this.setRunning(false);
	}

}

class ThreadX implements Runnable { // 实现java.lang.Runnable接口定义线程
	private Date runDate; // 线程被运行的时刻

	public void run() {
		System.out.println("线程X已经启动...");
		this.runDate = new Date();
		System.out.println("启动时间:" + runDate.toLocaleString());
	}
}

 

  实例223 参赛者的比赛生活(线程休眠唤醒)

package Chapter17.status;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Relay extends Thread {
	private DateFormat df = new SimpleDateFormat("ss:SS");
	public static void main(String[] args) { 	// java程序主入口处
		Relay relay = new Relay();		// 实例化对象
		relay.start(); 					// 启动线程
		try {
			relay.join(); 				// 等待线程运行结束
		} catch (InterruptedException e) {	// 捕获唤醒异常
			System.out.println(" 收到命令,准备上场:" + e.getMessage());
		}
		relay.incident(); 				// 调用方法判断是否唤醒
	}
	public void incident() {
		Thread.currentThread().interrupt(); 	// 唤醒当前线程
		while (true) {
			if (Thread.currentThread().isInterrupted()) { // 判断当前线程是否被唤醒
				System.out.print(df.format(new Date()) + "	现在是否正在准备上场? ");
				System.out.println(Thread.currentThread().isInterrupted() ? "是"
						: "没有");
				try {
					Thread.currentThread().sleep(3000); // 线程休眠3秒
				} catch (InterruptedException e) {		// 捕获唤醒异常
					System.out.println(df.format(new Date()) + " 收到命令,停止休息:"
							+ e.getMessage());
				}
				System.out.print(df.format(new Date()) + "	比赛结束后是否参加下一轮比赛? ");
				System.out.println(Thread.currentThread().isInterrupted() ? "是"
						: "不参加");
			}
		}
	}
	public void run() {
		System.out.println("第一场比赛结束的时间为:" + df.format(new Date()));
		System.out.println("休息5小时");
		try {
			sleep(2000); 				// 线程休眠2秒 在程序假设1秒钟=1小时
		} catch (InterruptedException e) { 	// 捕获唤醒异常
			System.out.println(df.format(new Date()) + "收到命令,准备上场:"
					+ e.getMessage());
		}
		System.out.print(df.format(new Date()) + "	在休息的过程中是否又参加其他的比赛? ");
		try {
			sleep(2000); 				// 线程休眠2秒
		} catch (InterruptedException e) { 	// 捕获唤醒异常
			System.out.println(df.format(new Date()) + "收到命令,准备上场:"
					+ e.getMessage());
		}
		System.out.println(!isAlive() ? "参加比赛" : "没有参加其他的比赛"); // 线程是否激活,false表不是激活的
		interrupt();// 唤醒线程
		System.out.print(df.format(new Date()) + " 休息中,替补队员受伤,是否参加比赛? ");
		System.out.println(isAlive() ? "参加比赛" : "不参加比赛"); // 线程是否激活
	}
	
}

 

  实例224 资源搜索并下载(线程等待和通报) 

package Chapter17.status;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class ResourceFile {
	private static boolean isStop = false;			// 标识线程是否停止
	private static List taskList = new ArrayList();	// 创建集合列表对象
	private static DateFormat dateFormat = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss");
	private class SearchDownload extends Thread {// 创建模拟搜索资源并下载文件类
		private String[] file = new String[] { "51Upload_Setup.exe",
				"eclipse-SDK-3.2.1-win32.zip", "EditPlus.rar" };
		// 创建模拟下载时所搜索的资源内容
		private String[] resource = new String[] { "开始连接......",
				"开始搜索候选资源......", "没搜索到候选资源,稍后重试搜索",
				"原始资源连接成功,得到的文件长度: 7725816", "开始创建文件......",
				"文件创建成功,开始下载数据......", "用户取消下载" };
		int sum = 0;//下载一个任务时用的总时间
		int time = 0;//搜索一个资源时用的时间
		public void run() {// 实现线程类的方法
			for (int i = 0; i < file.length; i++) {
				System.out.println("开始下载第" + (i + 1) + "个文件");
				try {
					for (int j = 0; j < resource.length; j++) {
						System.out.println(dateFormat.format(new Date()) + " "
								+ resource[j]);
						time = new Random().nextInt(100);	// 获得随机生成的秒数
						Thread.sleep(time);				// 线程休眠等待
						sum = sum + time;
					}
					System.out.println(dateFormat.format(new Date()) + " 下载文件"
							+ file[i] + "用时" + sum + " 毫秒. ");
					Thread.sleep(time);	// 线程休眠等待
				} catch (Exception e) {	// 捕获异常
					System.out.println("下载文件出错:" + e.getMessage());
				}
				synchronized (taskList) {	// 实现同步
					System.out.println(dateFormat.format(new Date()) + " "
							+ file[i] + "文件已下载完毕!");
					taskList.add(file[i]);	// 将文件添加到集合列表中
					taskList.notify();	// 通报所有等待的fileList的线程
				}
				sum = 0;
			}
			isStop = true;				// 重新设置标识
			System.out.println(dateFormat.format(new Date()) + " 下载线程 退出");
		}
	}
	public static void main(String[] args) {	// java程序主入口处
		ResourceFile text = new ResourceFile();	// 实例化对象
		text.new SearchDownload().start();		// 实例化内部类并启动线程
	}
}

 

  实例225 模拟淘宝购物买卖双方交易问题

package Chapter17;

import java.util.Random;

public class OnlineStore {
	public static void main(String[] args) {
		Alipay alipay = new Alipay(2); // 创建2个支付宝
		// 创建实例并启动线程
		new Seller("卖家-nieqing13", alipay, 5).start();
		new Seller("卖家-小不不88", alipay, 7).start();
		new Buyer("买家-淘之妖妖", alipay, 101).start();
		new Buyer("买家-相信美丽", alipay, 102).start();

	}
}

class Alipay { // 支付宝 用于网上买卖交易
	private final String[] goods;//标识卖家商品,数组的长度是多少则表示商品的数量是多少

	private int n; // 标识存入支付宝的交易数量

	private int m; // 标识支出支付宝的交易数量

	private int count; // 缓存内的交易数量

	public Alipay(int count) { // 构造方法进行初始化
		this.goods = new String[count]; // 创建字符串数组
		this.m = 0;
		this.n = 0;
		this.count = 0;
	}

	public synchronized void storage(String alipay) { // 往支付宝里存款
		System.out.println("淘宝用户ID=" + Thread.currentThread().getName()
				+ "\t支付宝存入" + alipay);
		try {
			while (count >= goods.length) {
				wait(); // 线程等待
			}
			goods[n] = alipay; // 放置支付宝账号于数组
			n = (n + 1) % goods.length;
			count++;
			notifyAll();
		} catch (Exception e) { // 捕获异常
			System.out.println("支付宝存入功能出现错误:" + e.getMessage());
		}
	}

	public synchronized String outlay() { // 从支付宝中支出
		String alipay = null;
		try {
			while (count <= 0) {
				wait(); // 线程等待
			}
			alipay = goods[m]; // 取出指定的支付宝账号
			m = (m + 1) % goods.length;
			count--; // 数组个数减一
			notifyAll();
		} catch (Exception e) { // 捕获异常
			System.out.println("支付宝支付功能出现错误:" + e.getMessage());
		}
		System.out.println("淘宝用户ID=" + Thread.currentThread().getName()
				+ "\t支付宝支出" + alipay);
		return alipay;
	}
}

class Buyer extends Thread { // 买家线程类
	private final Random random;

	private final Alipay alipay;

	private static int id = 0; // 交易的流水号

	public Buyer(String name, Alipay alipay, long seed) {// 构造方法进行初始化
		super(name);
		this.alipay = alipay;
		this.random = new Random(seed);
	}

	public void run() { // 实现Thread类的方法,启动线程
		try {
			while (true) {
				Thread.sleep(random.nextInt(1000));// 随机休眠
				String flowerID = "交易流水账号:" + nextId();
				alipay.storage(flowerID); // 存入支付宝中
			}
		} catch (Exception e) { // 捕获异常
		}
	}

	private static synchronized int nextId() {
		return id++;
	}
}

class Seller extends Thread { // 卖家线程类
	private final Random random;

	private final Alipay alipay;

	// 构造方法进行初始化
	public Seller(String name, Alipay alipay, long seed) {
		super(name);
		this.alipay = alipay;
		this.random = new Random(seed); // 创建随机对象
	}

	public void run() { // 实现Thread类的方法,启动线程
		try {
			while (true) {
				String alipay = this.alipay.outlay();
				Thread.sleep(random.nextInt(1000));
			}
		} catch (Exception e) { // 捕获异常
			System.out.println("买家支付预付款出错:" + e.getMessage());
		}
	}
}

 

  实例226 携子之手 与子偕老(join)

package Chapter17;

public class Partner {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MatchMarry group1 = new MatchMarry("TOM", "SUSAN"); // 实例化对象
		MatchMarry group2 = new MatchMarry("张三", "李小红");
		MatchMarry group3 = new MatchMarry("安妮", "罗卜特·波伊尔");
		MatchMarry group4 = new MatchMarry("TOM", "安妮");
		MatchMarry group5 = new MatchMarry("SUSAN", "张三");
		System.out.println("**速配婚姻介绍所,宗旨是要保证发扬\"携子之手 与子偕老\"的精神");
		group1.start(); // 启动线程
		try {
			group1.join(); // 等待线程运行结束
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
		group2.start();
		try {
			group2.join(); // 等待线程运行结束
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
		group3.start();
		try {
			group3.join(); // 等待线程运行结束
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}

		group4.start();
		try {
			group4.join(); // 等待线程运行结束
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
		group5.start();
		try {
			group5.join(); // 等待线程运行结束
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
		System.out.println("速配结束...");

	}

}

class MatchMarry extends Thread { // 测试匹配结婚的类
	private String name; // 人员名称

	private String otherName; // 结婚对象

	private boolean isMarry = false; // 是否结婚

	public MatchMarry(String name, String otherName) { // 带参数构造方法进行初始化
		this.name = name;
		this.otherName = otherName;
	}

	public void run() {
		try {
			int person = (int) Math.floor((Math.random() * 10 + 1));// 获得随机数
			if (person % 2 == 0) {
				isMarry = true; // 设置标识
			} else {
				isMarry = false;
			}
			if (!isMarry) {
				System.out.println(name + "可以与" + otherName + "结婚,祝福你们");
			} else {
				System.out.println(otherName + "已婚,红色警告:对待婚姻不要有二心");
			}
			Thread.sleep(200); // 线程休眠

		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
	}
}

 

  实例227 线程让步(Yield)

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;

public class TextThreadYield {					// 操作线程让步的类
	private Vector vector = new Vector();			// 创建向量集合
										// 创建日期格式
	private DateFormat dateFormat = new SimpleDateFormat("HH-mm-ss:SSSS"); 
	private boolean isFlag = false;
	private class Yield extends Thread {			//让步接收文件类
		public Yield() {
			this.setName("接收文件");			//设置线程名称
			this.setDaemon(true);			// 如果SendFile线程结束,则该线程自动结束
		}
		public void run() {
			while (!isFlag) {					// 标识为真进行循环
				try {
					Thread.sleep(100);		// 休眠
				}catch(InterruptedException e){	//捕获唤醒异常
					System.out.println("唤醒异常:"+e.getMessage());
				}
				if (vector.size() == 0) {		//判断向量集合大小
					System.out.println(dateFormat.format(new Date())+ "\t向量集合中没有文件,执行yield操作");
					Thread.yield();			//调用线程让步
				} else {					//移队文件获得对象
					String ss = (String) vector.remove(0); 
					System.out.println(dateFormat.format(new Date())+"\t取到文件,名为" + ss);
				}
			}
		}
	}
	private class SendFile extends Thread {		//发送文件类
		private String[] files = new String[] { "新闻文件", "国内旅游向导", "山水名画欣赏", "发家致富说明" };
		public SendFile() {
			this.setName("发送文件");
		}
		public void run() {
			try {
				for (int i=0;i < files.length;i++){	//循环使线程休眠
					Thread.sleep(201);		//线程休眠
					vector.add(files[i]);		//添加文件
				}
				Thread.sleep(100);			//线程休眠
			} catch (InterruptedException e) {	//捕获唤醒异常
				System.out.println("唤醒异常:"+e.getMessage());
			}
		}
	}
	public static void main(String []args){			//java程序主入口处
		TextThreadYield text=new TextThreadYield();//实例化对象
		text.new Yield().start();				//实例对象启动线程
		text.new SendFile().start();
	}
}

 

  实例228 会走动的钟(多线程) 

package Chapter17.status;

import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Date;

public class MoveClock extends Applet implements Runnable {
	Thread hourThread = null; 		// 时针线程
	Thread minuteThread = null; 		// 分针线程
	Thread secondThread = null; 		// 秒针线程
	int hourX, hourY, minuteX, minuteY, secondX, secondY;// 表示时,分,秒针端点的XY坐标点
	int currentHour = 0; 				// 获取当前时间中代表小时的数字值
	int currentMinute = 0; 			// 获取当前时间中代表分钟的数字值
	int currentSecond = 0; 			// 获取当前时间中代表秒的数字值
	Graphics secondGraphics = null; 	// 绘制秒针的Graphics对象
	Graphics minuteGraphics = null; 	// 绘制分针的Graphics对象
	Graphics hourGraphics = null; 		// 绘制时针的Graphics对象
	Graphics2D minuteg2D = null;		// 创建Graphics2D对象
	Graphics2D hourg2D = null;		// 创建Graphics2D对象
	Graphics2D secondg2D = null;		// 创建Graphics2D对象
	double drawX[] = new double[61]; 	// 存放表盘刻度的X轴数组
	double drawY[] = new double[61]; 	// 存放表盘刻度的Y轴数组
	double dial_x[] = new double[61]; 	// 供绘制表盘使的x点坐标值
	double dial_y[] = new double[61];	// 供绘制表盘使的Y点坐标值
	int isRestart = 0; 	// 判断是否重新开始
	public void init() { 	// 数据初始化
		hourGraphics = this.getGraphics(); 		// 实例化时针Graphics对象
		hourGraphics.setColor(Color.white); 	// 设置时针的颜色
		hourg2D = (Graphics2D) hourGraphics;	// 实例化时针Graphics2D对象
		hourGraphics.translate(200, 200); 		// 进行坐标系统变换原点设在(200,200)处
		minuteGraphics = this.getGraphics(); 	// 实例化分针Graphics对象
		minuteg2D = (Graphics2D) minuteGraphics;	// 实例化分针Graphics2D对象
		minuteGraphics.setColor(Color.green); 		// 设置分针的颜色
		minuteGraphics.translate(200, 200); 		// 进行坐标系统变换,原点设在(200,200)处
		secondGraphics = this.getGraphics(); 		// 实例化秒针Graphics对象
		secondg2D = (Graphics2D) secondGraphics;	// 实例化秒针Graphics2D对象
		secondGraphics.setColor(Color.blue); 		// 设置秒针的颜色
		secondGraphics.translate(200, 200); 		// 进行坐标系统变换,原点设在(200,200)处
		drawX[0] = 0;
		// 各个时针12点处的位置坐标(按新坐标系的坐标)
		drawY[0] = -120;
		dial_x[0] = 0;
		// 12点处的刻度位置坐标(按新坐标系的坐标)
		dial_y[0] = -140;
		double jiaodu = 6 * Math.PI / 180;
		// 表盘分割成60分,将分割点的坐标存放在数组中
		for (int i = 0; i < 60; i++) {
			drawX[i + 1] = drawX[i] * Math.cos(jiaodu) - Math.sin(jiaodu)
					* drawY[i];
			drawY[i + 1] = drawY[i] * Math.cos(jiaodu) + drawX[i]
					* Math.sin(jiaodu);
		}
		drawX[60] = 0;
		drawY[60] = -120;
		// 表盘分割成60分,将分割点的坐标存放在绘制数组中
		for (int i = 0; i < 60; i++) {
			dial_x[i + 1] = dial_x[i] * Math.cos(jiaodu) - Math.sin(jiaodu)
					* dial_y[i];
			dial_y[i + 1] = dial_y[i] * Math.cos(jiaodu) + Math.sin(jiaodu)
					* dial_x[i];
		}
		dial_x[60] = 0;
		dial_y[60] = -140;
	}
	public void start() {
		if (isRestart >= 1) {
			secondThread.interrupt(); 	// 唤醒线程
			minuteThread.interrupt();
			hourThread.interrupt();
		}
		hourThread = new Thread(this); 	// 创建时针线程
		minuteThread = new Thread(this); 	// 创建分针线程
		secondThread = new Thread(this); 	// 创建秒针线程
		secondThread.start(); 			// 启动秒针线程
		minuteThread.start(); 			// 启动分针线程
		hourThread.start(); 				// 启动时针线程
		isRestart++;
		if (isRestart >= 2)
			isRestart = 1;
	}
	public void stop() {
		secondThread.interrupt(); // 唤醒线程
		minuteThread.interrupt();
		hourThread.interrupt();
	}
	public void paint(Graphics g) { // 绘制图形
		this.setBackground(Color.black);
		this.start();
		g.drawOval(50, 50, 300, 300);	// 表盘的外圈
		g.translate(200, 200); 		// 进行坐标系统变换
		for (int i = 0; i < 60; i++) { 		// 绘制表盘的小刻度和大刻度
			if (i % 5 == 0) {
				g.setColor(Color.red); // 设置颜色
				g.fillOval((int) dial_x[i], (int) dial_y[i], 10, 10);
			} else
				g.fillOval((int) dial_x[i], (int) dial_y[i], 5, 5);
		}
	}
	public void run() { 			// 实现Thread的方法,开始线程
		Date date = new Date(); 	// 获取本地时间
		String string = date.toString();
		currentHour = Integer.parseInt(string.substring(11, 13)); 	// 获得当前时间的小时
		currentMinute = Integer.parseInt(string.substring(14, 16)); // 获取当前时间的分钟
		currentSecond = Integer.parseInt(string.substring(17, 19));// 获取当前时间的秒钟
		if (Thread.currentThread() == secondThread) { 		// 如果当前线程是秒线程
			secondX = (int) drawX[currentSecond]; 			// 秒针初始化
			secondY = (int) drawX[currentSecond];
			// 用背景色清除前一秒的秒针
			secondGraphics.drawLine(0, 0, secondX, secondY);
			secondg2D.setStroke(new BasicStroke(2.0f));		// 设置所绘制秒针的宽度
			int i = currentSecond;
			while (true) {
				try {
					secondThread.sleep(1000); 			// 每隔一秒休眠
					Color c = getBackground(); 			// 获取背景颜色
					secondGraphics.setColor(c); 			// 设置秒针的颜色
					// 用背景色清除前一秒的秒针
					secondGraphics.drawLine(0, 0, secondX, secondY);
					secondg2D.setStroke(new BasicStroke(2.0f));
					// 秒针与分针重合,恢复分针显示
					if ((secondX == minuteX) && (secondY == minuteY)) {
						// 用背景色清除前一分的分针
						minuteGraphics.drawLine(0, 0, minuteX, minuteY);
					}
					// 秒针与时针重合,恢复时针的显示
					if ((secondX == hourX) && (secondY == hourY)) {
						// 用背景色清除前一时的时针
						hourGraphics.drawLine(0, 0, hourX, hourY);
						hourg2D.setStroke(new BasicStroke(4.0f));// 设置所绘制时针的宽度
					}
				} catch (InterruptedException e) { 	// 捕获异常
					Color c = getBackground(); 	// 获取背景颜色
					secondGraphics.setColor(c);	// 设置秒针的颜色
					// 用背景色清除秒针
					secondGraphics.drawLine(0, 0, secondX, secondY);
					secondg2D.setStroke(new BasicStroke(2.0f));
					return;
				}
				secondX = (int) drawX[(i + 1) % 60]; 	// 秒针向前走一个单位
				secondY = (int) drawY[(i + 1) % 60]; 	// 每一秒走6度(一个单位格)
				secondGraphics.setColor(Color.blue);	// 绘制秒针的颜色
				// 用背景色清除前一秒的秒针
				secondGraphics.drawLine(0, 0, secondX, secondY);
				secondg2D.setStroke(new BasicStroke(2.0f));
				i++;
			}
		}
		if (Thread.currentThread() == minuteThread) { 		// 如果当前线程是分线程
			minuteX = (int) drawX[currentMinute];
			minuteY = (int) drawY[currentMinute];
			minuteGraphics.drawLine(0, 0, minuteX, minuteY);
			minuteg2D.setStroke(new BasicStroke(3.0f));
			int i = currentMinute; // 获取当前分钟
			while (true) {
				try { // 第一次过60-second秒就前进一分钟,以后每过60秒前进一分钟
					minuteThread.sleep(1000 * 60 - currentSecond * 1000);
					currentSecond = 0;
					Color c = getBackground(); 		// 获取背景颜色
					minuteGraphics.setColor(c); 		// 设置分针的颜色
					minuteg2D.setStroke(new BasicStroke(3.0f));// 设置所绘制分针的宽度
					minuteGraphics.drawLine(0, 0, minuteX, minuteY);
					// 如果时针和分针重合
					if ((hourX == minuteX) && (hourY == minuteY)) {
						hourGraphics.drawLine(0, 0, minuteX, minuteY);
						hourg2D.setStroke(new BasicStroke(4.0f));
					}
				} catch (InterruptedException e) {
					return;
				}
				minuteX = (int) drawX[(i + 1) % 60]; 		// 分针向前走一个单位
				minuteY = (int) drawY[(i + 1) % 60]; 		// 每一分走6度(一个单位格)
				minuteGraphics.setColor(Color.BLUE); 	// 绘制分针的颜色
				minuteg2D.setStroke(new BasicStroke(3.0f));
				minuteGraphics.drawLine(0, 0, minuteX, minuteY);
				i++;
				currentSecond = 0;
			}
		}
		if (Thread.currentThread() == hourThread) { // 如果当前线程是时线程
			int h = currentHour % 12;
			hourX = (int) drawX[h * 5 + currentMinute / 12];
			hourY = (int) drawY[h * 5 + currentMinute / 12];
			int i = h * 5 + currentMinute / 12;
			hourGraphics.drawLine(0, 0, hourX, hourY);
			hourg2D.setStroke(new BasicStroke(4.0f));
			while (true) {
				try {
					// 第一次过12-minute%12分钟就前进一个刻度,以后每过12分钟前进一刻度
					hourThread.sleep(1000 * 60 * 12 - 1000 * 60
							* (currentMinute % 12) - currentSecond * 1000);
					currentMinute = 0;
					Color c = getBackground();
					hourGraphics.setColor(c);
					hourGraphics.drawLine(0, 0, hourX, hourY);
					hourg2D.setStroke(new BasicStroke(4.0f));
				} catch (InterruptedException e) {
					return;
				}
				hourX = (int) drawX[(i + 1) % 60];
				hourY = (int) drawY[(i + 1) % 60];
				hourGraphics.setColor(Color.BLACK);
				hourGraphics.drawLine(0, 0, hourX, hourY);
				hourg2D.setStroke(new BasicStroke(4.0f));
				i++;
				currentMinute = 0;
			}
		}
	}
}

 

  实例229 变形金刚中的守护神(守护线程)

package Chapter17.status;
public class Transformer {						// 本程序的测试类
	public static void main(String[] args) { 		// java程序执行入口处
		Defensor defensor = new Defensor(); 	// 默认情况下父类Defensor是普通线程
		defensor.start(); 					// 启动Defensor类线程
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) { 		// 捕获被唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		}
	}
}
class Defensor extends Thread { 				// 操作守护神线程的类
	public void run() {
		System.out.print("当霸天虎在袭击地球的危难关头,守护神是否采取自我保护? ");
		System.out.println(this.isDaemon() ? "是" : "没有");// 测试该线程是否为守护线程。
		System.out.println("守护神Defensor是机器卫兵的组合战士,个性善良,愿意牺牲自己去保护人类");
		Human people = new Human();
		people.setDaemon(true); // 设置守护线程,在本程序中将其子类people设置为守护线程也就是被保护的对象
		people.start();			// 启动守护线程
		try {
			Thread.sleep(1000); // 休眠1秒
		} catch (InterruptedException e) { 	// 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		} finally { 						// 内容总执行
			System.out.println("在面对危险的时候,守候神舍身捍卫地球,保护人类的安全");
		}
		System.out.println("守候神太伟大了...");
	}
}
class Human extends Thread {
	public void run() {
		System.out.print("人类的安全是否被保护?");
		System.out.println(this.isDaemon() ? "是" : "没有");// 判断此线程是否是守护线程
		System.out.println("现在有5处场所的人们正处于危险之中!!!");
		int i = 0;
		try {
			while (i < 5) { 			// 进行5次循环
				System.out.println("第" + (1 + i++) + "处场所的人类");
				Thread.sleep(200); 	// 休眠0.2秒
			}
		} catch (InterruptedException e) { // 捕获唤醒异常
			System.out.println("唤醒异常:" + e.getMessage());
		} finally { 						// 内容总执行
			System.out.println("守候神尽心尽力,帮助人类安全的躲过霸天虎的疯狂袭击");
		}
		System.out.println("终于脱离危险了~~~");
	}
}

 

  实例230 查看JVM中所有的线程的活动状况

public class ThreadAction {// 操作查看JVM虚拟机中所的线程和线程组的类
	// 显示线程信息
	private static void threadMessage(Thread thread, String index) {
		if (thread == null)
			return;
		System.out.println(index + "ThreadName- " + thread.getName()
				+ "  Priority- " + thread.getPriority()
				+ (thread.isDaemon() ? " Daemon" : "")
				+ (thread.isAlive() ? "" : " Inactive"));
	}
	// 显示线程组信息
	private static void threadGroupMessage(ThreadGroup group, String index) {
		if (group == null)
			return; // 判断线程组
		int count = group.activeCount(); // 获得活动的线程数
		// 获得活动的线程组数
		int countGroup = group.activeGroupCount();
		// 根据活动的线程数创建指定个数的线程数组
		Thread[] threads = new Thread[count];
		// 根据活动的线程组数创建指定个数的线程组数组
		ThreadGroup[] groups = new ThreadGroup[countGroup];
		group.enumerate(threads, false); // 把所有活动子组的引用复制到指定数组中,false表示不包括对子组的所有活动子组的引用
		group.enumerate(groups, false);
		System.out.println(index + "ThreadGroupName-" + group.getName()
				+ "MaxPriority- " + group.getMaxPriority()
				+ (group.isDaemon() ? " Daemon" : ""));
		// 循环显示当前活动的线程信息
		for (int i = 0; i < count; i++)
			threadMessage(threads[i], index + "    ");
		for (int i = 0; i < countGroup; i++)
			// 循环显示当前活动的线程组信息
			threadGroupMessage(groups[i], index + "    ");// 递归调用方法
	}
	public static void threadsList() { // 找到根线程组并列出它递归的信息
		ThreadGroup currentThreadGroup; // 当前线程组
		ThreadGroup rootThreadGroup; // 根线程组
		ThreadGroup parent;
		// 获得当前活动的线程组
		currentThreadGroup = Thread.currentThread().getThreadGroup();
		rootThreadGroup = currentThreadGroup; // 获得根线程组
		parent = rootThreadGroup.getParent(); // 获得根线程
		while (parent != null) { // 循环对根线程组重新赋值
			rootThreadGroup = parent;
			parent = parent.getParent();
		}
		threadGroupMessage(rootThreadGroup, ""); // 显示根线程组
	}
	public static void main(String[] args) { // java程序主入口处
		System.out.println("查看JVM中所有的线程的活动状况如下:");
		ThreadAction.threadsList(); // 调用方法显示所有线程的信息
	}
}

 

  实例231 模仿网络快车下载工具下载文件 

package Chapter17.status;

import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class FreshDownload extends JFrame {
	private JPanel mainPanel; // 网络快车的主面板
	private JTextField webField = new JTextField(); // 下载地址的文本框
	private JTextField localFile = new JTextField(); // 下载到本地的文本框
	private JTextField fileNameField = new JTextField(); // 文件名对应的文本框
	private JTextField categoryField = new JTextField(); // 分类对应的文本框
	private JButton button = new JButton(); // 下载按钮
	private JButton button1 = new JButton(); // 取消下载按钮
	private JLabel targetLabel = new JLabel(); // 目标标签
	private JLabel localLabel = new JLabel(); // 下载到本地标签
	private JLabel fileName = new JLabel(); // 下载的文件名
	private JLabel category = new JLabel(); // 分类
	private JLabel content = new JLabel(); // 信息内容
	private JLabel tips = new JLabel(); // 信息提示
	private JTextArea textArea = new JTextArea(); // 显示下载记录的文本域
	private String urlPath = new String(); // 下载地址
	private String saveFileAs = new String(); // 另存为
	public FreshDownload() { // 构造方法进行初始化
		enableEvents(AWTEvent.WINDOW_EVENT_MASK);
		try {
			initPanel(); // 调用方法初始化面板
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	private void initPanel() throws Exception { // 初始化面板
		mainPanel = (JPanel) this.getContentPane(); // 创建面板
		mainPanel.setLayout(null); // 没有设置面板布局
		this.setSize(new Dimension(480, 420)); // 面板的大小
		this.setLocation(100, 100); // 面板位置
		this.setTitle("模仿网络快车多线程下载"); // 面板标题
		targetLabel.setBounds(new Rectangle(20, 20, 120, 20)); // 标签的位置
		targetLabel.setText("下载网址: ");
		webField.setBounds(new Rectangle(100, 20, 250, 20)); // 设置文本框的位置
		// 设置默认下载路径
	webField.setText("http://zhanjia.javaeye.com/topics/download/d3682cdf-04be-3a57-89a4-93cbef5ae038");
		fileName.setText("文件名:");
		fileName.setBounds(20, 50, 120, 20);// 文件名标签的位置
		fileNameField.setText("java实例.jar");// 文件文本框中默认的内容
		fileNameField.setBounds(100, 50, 120, 20);// 文件文本框中的位置
		category.setText("分类:");
		category.setBounds(20, 80, 120, 20);// 分类标签的位置
		categoryField.setText("其他");
		categoryField.setBounds(100, 80, 120, 20);// 分类文本框中的位置
		localLabel.setBounds(new Rectangle(20, 110, 120, 20)); // 标签的位置
		localLabel.setText("下载到: ");
		localFile.setBounds(new Rectangle(100, 110, 120, 20)); // 设置文本框的位置
		localFile.setText("F:\\Downloads");// 设置默认另存为
		button.setBounds(new Rectangle(230, 110, 60, 20)); // 按钮的位置
		button.setText("下载");
		button1.setBounds(new Rectangle(290, 110, 60, 20)); // 按钮的位置
		button1.setText("取消");
		tips.setBounds(new Rectangle(20, 130, 120, 20)); // 标签的位置
		tips.setText("信息提示: ");
		content.setText("F盘可用空间71.7GB,任务所需空间24.3MB");
		content.setBounds(100, 130, 250, 20);
		button.addActionListener(new ActionListener() { // 按钮添加监听事件
					public void actionPerformed(ActionEvent e) {
						getActionPerformed(e); // 调用事件
					}
				});
		// 创建有滑动条的面板将文本域放在上面
		JScrollPane scrollPane = new JScrollPane(textArea);
		scrollPane.setBounds(new Rectangle(20, 160, 400, 200)); // 面板的位置
		textArea.setEditable(false); // 不可编辑
		mainPanel.add(webField, null); // 将文本框添加到面板中
		mainPanel.add(localFile, null); // 将文本框添加到面板中
		mainPanel.add(fileName, null);// 将文件名标签添加到面板中
		mainPanel.add(fileNameField, null);// 将文件名文本框添加到面板中
		mainPanel.add(category, null);// 将分类标签添加到面板中
		mainPanel.add(categoryField, null);// 将分类文本框添加到面板中
		mainPanel.add(targetLabel, null); // 将标签添加到面板中
		mainPanel.add(localLabel, null); // 将标签添加到面板中
		mainPanel.add(button, null); // 将下载按钮添加到面板中
		mainPanel.add(button1, null); // 将取消按钮添加到面板中
		mainPanel.add(tips, null); // 将标签添加到面板中
		mainPanel.add(content, null); // 将标签添加到面板中
		mainPanel.add(scrollPane, null); // 将滑动条添加到面板中
		urlPath = webField.getText(); // 获得文本框中的文本
		saveFileAs = localFile.getText();// 获得文本框中的文本
		this.setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置默认关闭操作
	}
	// 点击事件触发方法,启动分析下载文件的进程
	public void getActionPerformed(ActionEvent e) {
		urlPath = webField.getText(); // 获得目标文件的网址
		saveFileAs = localFile.getText(); // 获得另存为的地址
		if (urlPath.compareTo("") == 0)
			textArea.setText("请输入要下载的文件完整地址");
		else if (saveFileAs.compareTo("") == 0) {
			textArea.setText("请输入保存文件完整地址");
		} else {
			try {
				SearchAndDown downFile = new SearchAndDown(urlPath, saveFileAs,
						5, textArea); // 传参数实例化下载文件对象
				downFile.start(); // 启动下载文件的线程
				textArea.append("主线程启动...");
			} catch (Exception ec) { // 捕获异常
				System.out.println("下载文件出错:" + ec.getMessage());
			}
		}
	}
	public static void main(String[] args) { // java程序主入口处
		FreshDownload frame = new FreshDownload(); // 实例化对象进行初始化
		frame.setVisible(true); // 设置窗口可视
	}
}
class SearchAndDown extends Thread { // 分析下载的文件并启动下载进程
	String urlPath; // 下载文件的地址
	String saveFileAs; // 文件另存为
	int threadCount; // 线程总数
	String log = new String(); // 下载过程的日志记录
	JTextArea textArea = new JTextArea(); // 创建文本域
	long[] position;
	long[] start; // 每个线程开始位置
	long[] end; // 每个线程结束位置
	BatchFile[] file; // 子线程对象
	long fileLength; // 下载的文件的长度
	public SearchAndDown(String urlPath, String saveFileAs, int threadCount,
			JTextArea textArea) { // 构造方法进行初始化
		this.urlPath = urlPath;
		this.saveFileAs = saveFileAs;
		this.threadCount = threadCount;
		this.textArea = textArea;
		start = new long[threadCount];
		end = new long[threadCount];
	}
	public void run() { // 实现Thread类的方法
		log = "目标文件: " + urlPath;
		textArea.append("\n" + log); // 日志写入文本域
		log = "\n 线程总数: " + threadCount;
		textArea.append("\n" + log);
		try {
			fileLength = getSize(); // 获得文件长度
			if (fileLength == -1) { // 不可获取文件长度或没找到资源
				textArea.append("\n 不可知的文件长度!请重试!!");
			} else {
				if (fileLength == -2) { // 无法获取文件或没有找到资源
					textArea.append("\n 文件无法获取,没有找到指定资源,请重试!!");
				} else { // 循环对每个线程的开始位置赋值
					for (int i = 0; i < start.length; i++) {
						start[i] = (long) (i * (fileLength / start.length));
					}
					for (int i = 0; i < end.length - 1; i++)
						// 循环对每个线程的结束位置赋值
						end[i] = start[i + 1];
					// 最后一线程结束位置是文件长度
					end[end.length - 1] = fileLength;
					for (int i = 0; i < start.length; i++) { // 循环显示每线程开始和结束位置
						log = "线程:" + i + "下载范围:" + start[i] + "--" + end[i];
						textArea.append("\n" + log);
					}
					file = new BatchFile[start.length];
					for (int i = 0; i < start.length; i++) { // 启动一组子线程
						file[i] = new BatchFile(urlPath, saveFileAs, start[i],
								end[i], i, textArea);
						log = "线程 " + i + "启动";
						textArea.append("\n" + log);
						file[i].start(); // 启动线程
					}
					boolean breakWhile = true;
					while (breakWhile) { // 当条件始终为true时进行循环
						Thread.sleep(500); // 线程休眠
						breakWhile = false;
						for (int i = 0; i < file.length; i++) {
							if (!file[i].isDone) { // 循环判断每个线程是否结束
								breakWhile = true;
								break;
							}
						}
					}
					textArea.append("\n文件传输结束!");// 文件传输结束
				}
			}
		} catch (Exception ex) { // 捕获异常
			ex.printStackTrace();
		}
	}
	public long getSize() { // 获得文件的长度的方法
		int fileLength = -1;
		try {
			URL url = new URL(urlPath); // 根据网址创建URL对象
			HttpURLConnection httpConnection = (HttpURLConnection) (url
					.openConnection()); // 创建远程对象连接对象
			int responseCode = httpConnection.getResponseCode();
			if (responseCode >= 400) { // 没有获得响应信息
				System.out.println("Web服务器响应错误");
				return -2; // Web服务器响应错误
			}
			String sHeader;
			for (int i = 1;; i++) { // 查标识文件长度文件头获文件长度
				sHeader = httpConnection.getHeaderFieldKey(i);
				if (sHeader != null) {
					if (sHeader.equals("Content-Length")) {// 查找标识文件长度的文件头
						fileLength = Integer.parseInt(httpConnection
								.getHeaderField(sHeader));
						break;
					}
				} else {
					break;
				}
			}
		} catch (Exception e) { // 捕获异常
			System.out.println("无法获得文件长度:" + e.getMessage());
		}
		return fileLength;
	}
}
class BatchFile extends Thread {
	String urlPath; // 下载文件的地址
	long start; // 线程的开始位置
	long end; // 线程的结束位置
	int threadID;
	JTextArea textArea = new JTextArea(); // 创建文本域
	boolean isDone = false; // 是否下载完毕
	RandomAccessFile random;
	public BatchFile(String urlPath, String saveAs, long nStart, long nEnd,
			int id, JTextArea textArea) {
		this.urlPath = urlPath;
		this.start = nStart;
		this.end = nEnd;
		this.threadID = id;
		this.textArea = textArea;
		try {
			random = new RandomAccessFile(saveAs, "rw"); // 创建随机访问对象,以读/写方式
			random.seek(start); // 定位文件指针到startPosition位置
		} catch (Exception e) { // 捕获异常
			System.out.println("创建随机访问对象出错:" + e.getMessage());
		}
	}
	public void run() { // 实现Thread类的方法
		try {
			URL url = new URL(urlPath); // 根据网址创建URL对象
			HttpURLConnection httpConnection = (HttpURLConnection) url
					.openConnection(); // 创建远程对象连接对象
			String sProperty = "bytes=" + start + "-";
			httpConnection.setRequestProperty("RANGE", sProperty);
			textArea.append("\n 线程" + threadID + "下载文件!  请等待...");
			InputStream input = httpConnection.getInputStream();// 获得输入流对象
			byte[] buf = new byte[1024]; // 创建字节数据存储文件的数据
			int splitSpace;
			splitSpace = (int) end - (int) start; // 获得每个线程的间隔
			if (splitSpace > 1024)
				splitSpace = 1024;
			// 读取文件信息
			while (input.read(buf, 0, splitSpace) > 0 && start < end) {
				splitSpace = (int) end - (int) start;
				if (splitSpace > 1024)
					splitSpace = 1024;
				textArea.append("\n线程: " + threadID + " 开始位置: " + start
						+ ",  间隔长度: " + splitSpace);
				random.write(buf, 0, splitSpace); // 写入文件
				start += splitSpace; // 开始位置改变
			}
			textArea.append("\n 线程" + threadID + "下载完毕!!");
			random.close(); // 释放资源
			input.close();
			isDone = true;
		} catch (Exception e) { // 捕获异常
			System.out.println("多线程下载文件出错:" + e.getMessage());
		}
	}
}

 

  13.2 多线程的同步与互斥 

  实例232 多线程同步方法的实例

package Chapter17;

public class SyncExample {
	public static void main(String[] args) {
		SyncThread t1 = new SyncThread(); // 创建SyncThread类的实例对象
		new Thread(t1, "线程1").start(); // 创建线程并启动它
		new Thread(t1, "线程2").start(); // 创建线程并启动它
		System.out.println(t1.Perform()); // 调用SyncThread类的同步方法call()
	}

}

class SyncThread implements Runnable {
	private int x = 5;

	private int y = 5;

	// 定义SyncThread的同步方法
	public synchronized void run() { // 重写Runnable接口的run(),并声明成synchronized
		for (int i = 0; i < 4; i++) {
			x++;
			y++;
			try {
				Thread.sleep(200); // 当前运行的线程休眠200毫秒
			} catch (InterruptedException e) {
				System.out.println("线程出错了");
			}
			System.out.println(Thread.currentThread().getName() + " x=" + x
					+ ",y=" + y);
		}
	}

	public synchronized String Perform() { // 自定义方法,并声明成synchronized
		String name = Thread.currentThread().getName();
		return "当前正在运行的线程: " + name;
	}
}

 

  实例233 ATM存取一体机(线程同步互斥) 

package Chapter17;

public class ATMCashMachines {
	public static void main(String[] args) { // java程序主入口处
		Bank bank = new Bank();// 实例化Bank对象
		SyncBank sbank = new SyncBank();// 实例化SyncBank对象
		System.out.println("1.存、取线程没有采取同步时,执行存取操作时,其工作流程如下:");
		// 存钱没有采用同步机制
		Thread putThread = new CashMachines(bank, "saveMoney");
		// 取钱没有同步机制
		Thread takeThread = new CashMachines(bank, "withdrawMoney");
		putThread.start(); // 启动putThread线程
		takeThread.start(); // 启动takeThread线程
		try {
			putThread.join(); // 等待两线程运行结束
			takeThread.join();
		} catch (Exception e) { // 捕获异常
			System.out.println("两线程运行出错:" + e.getMessage());
		}
		System.out.println();
		bank = new Bank();
		System.out.println("2.存、取线程设置为同步时,执行存取操作时,其工作流程如下:");
		putThread = new CashMachines(sbank, "sync_SaveMoney"); // 创建CashMachines对象,存钱有同步机制
		takeThread = new CashMachines(sbank, "sync_WithdrawMoney"); // 取钱有同步机制
		putThread.start(); // 启动线程
		takeThread.start(); // 启动线程
	}

}

class Bank {
	private double curveMoney = 174.85; // 存入银行的钱数

	public void saveMoney(double putThread) { // 存钱没有采用同步机制
		System.out.println("当前账户中所剩余额为" + this.curveMoney + "; 存入金额为: "
				+ putThread);
		System.out.println("正在操作,请稍候......"); // 存钱时先等待300毫秒
		try {
			Thread.sleep(300); // 线程休眠
		} catch (Exception e) { // 捕获异常
			e.printStackTrace();
		}
		System.out.println("操作成功,存入金额:" + putThread);
		this.curveMoney = this.curveMoney + putThread;
		System.out.println("当前余额为:" + this.curveMoney + "元");
	}

	public void withdrawMoney(double takeThread) { // 取钱没有同步机制
		System.out.println("查询余额显示,当前可用余额为:" + this.curveMoney + "; 取出金额为: "
				+ takeThread);
		System.out.println("正在操作,请稍候......"); // 取钱时先等待500毫秒
		try {
			Thread.sleep(500); // 线程休眠
		} catch (Exception e) { // 捕获异常
			e.printStackTrace();
		}
		System.out.println("操作成功,取出金额:" + takeThread);
		this.curveMoney = this.curveMoney - takeThread;
		System.out.println("当前余额为:" + this.curveMoney + "元");
	}

}

class SyncBank {
	private double curveMoney = 174.85; // 存入银行的钱数

	public synchronized void sync_SaveMoney(double putThread) { // 存钱有同步机制
		System.out.println("当前账户中所剩余额为" + this.curveMoney + "; 存入金额为: "
				+ putThread);
		System.out.println("正在操作,请稍候......"); // 存钱时先等待300毫秒
		try {
			Thread.sleep(300); // 线程休眠
		} catch (Exception e) { // 捕获异常
			e.printStackTrace();
		}
		System.out.println("操作成功,存入金额:" + putThread);
		this.curveMoney = this.curveMoney + putThread;
		System.out.println("当前余额为:" + this.curveMoney + "元");
	}

	public synchronized void sync_WithdrawMoney(double takeThread) {// 取钱有同步机制
		System.out.println("查询余额显示,当前可用余额为:" + this.curveMoney + "; 取出金额为: "
				+ takeThread);
		System.out.println("正在操作,请稍候......"); // 取钱时先等待500毫秒
		try {
			Thread.sleep(500); // 线程休眠
		} catch (Exception e) { // 捕获异常
			e.printStackTrace();
		}
		System.out.println("操作成功,取出金额:" + takeThread);
		this.curveMoney = this.curveMoney - takeThread;
		System.out.println("当前余额为:" + this.curveMoney + "元");
	}
}

class CashMachines extends Thread { // 继承Thread类实现线程方法
	private Bank bank = null; // 待访问的帐号对象

	private SyncBank sbank = null; // 待访问的帐号对象

	private String account = ""; // 访问帐号的方法

	public CashMachines(Bank bank, String account) { // 构造方法进行初始化
		this.account = account;
		this.bank = bank;
	}

	public CashMachines(SyncBank sbank, String account) { // 构造方法进行初始化
		this.account = account;
		this.sbank = sbank;
	}

	public void run() { // 实现Thread的方法
		if (account.equals("saveMoney")) { // 不同参数调用不同的方法
			bank.saveMoney(800.0);
		} else if (account.equals("withdrawMoney")) {
			bank.withdrawMoney(300.0);
		} else if (account.equals("sync_SaveMoney")) {
			sbank.sync_SaveMoney(800.0);
		} else if (account.equals("sync_WithdrawMoney")) {
			sbank.sync_WithdrawMoney(300.0);
		}
	}
}

 

  实例234 我的钱哪里去了

package Chapter17;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class SavingOffice extends Frame implements ActionListener {
	private Label label = new Label("转账已完成:0");

	// 创建AWT多行文本组件
	private TextArea area = new TextArea();

	// 创建AWT按扭组件
	private Button display = new Button("显示帐户");

	private Button start = new Button("重新启动");

	private Button stop = new Button("停止");

	// 声明账号的个数
	protected final static int num_accounts = 8;

	// 定义浪沸的时间
	private final static int waste_time = 1;

	// 创建一个int型数组,用于存入账号的初始金额
	private int accounts[] = new int[num_accounts];

	// 创建一个Customer数组,用于存放Customer实例化对象
	private Customer customer[] = new Customer[num_accounts];

	// 表法转账的金额
	private int count = 0;

	public SavingOffice() {// 构造方法,为其AWT成员变量进行初始化
		super("我的秘密小金库");
		Panel btn_Panel = new Panel();
		btn_Panel.setLayout(new FlowLayout());
		btn_Panel.add(display);
		display.addActionListener(this);
		btn_Panel.add(start);
		start.addActionListener(this);
		btn_Panel.add(stop);
		stop.addActionListener(this);
		setLayout(new BorderLayout());
		add("North", label);
		add("South", btn_Panel);
		add("Center", area);
		for (int i = 0; i < accounts.length; i++)
			accounts[i] = 50000;// 每个账户上的初始金额为5万元
		start();// 是普通的方法,并非线程的start方法
		validate();
		setSize(300, 300);
		setVisible(true);
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				System.exit(0);
			}
		});
	}

	public void transfer(int from, int into, int amount) {// 进行转账
		if ((accounts[from] >= amount) && (from != into)) {
			int newAmountFrom = accounts[from] - amount;
			int newAmountTo = accounts[into] + amount;
			wastrSomeTime();
			accounts[from] = newAmountFrom;
			accounts[into] = newAmountTo;

		}
		label.setText("转账完成:" + count++);
	}

	public void start() {// 启动程序
		stop();
		for (int i = 0; i < accounts.length; i++)
			customer[i] = new Customer(i, this);
	}

	private void stop() {// 停止
		for (int i = 0; i < accounts.length; i++)
			if (customer[i] != null)
				customer[i].setFlagValue();
	}

	private void wastrSomeTime() {// 处于等待休眠中
		try {
			Thread.sleep(waste_time);
		} catch (InterruptedException ie) {
			System.out.println(ie);
		}
	}

	private void showAccounts() {// 显示金额
		int sum = 0;
		for (int i = 0; i < accounts.length; i++) {
			sum += accounts[i];
			area.append("\n帐户 " + i + ":$" + accounts[i]);
		}
		area.append("\n总金额:$" + sum);
		area.append("\n转账总次数:" + count + "\n");
	}

	public void actionPerformed(ActionEvent ae) {// 为button组件添别事件监听
		if (ae.getSource() == display)
			showAccounts();
		else if (ae.getSource() == start)
			start();
		else if (ae.getSource() == stop)
			stop();
	}

	public static void main(String args[]) {
		SavingOffice bank = new SavingOffice();
	}
}

class Customer extends Thread {// 顾客类
	private SavingOffice bank = null;

	private int id = -1;

	private boolean flag = false;

	public Customer(int _id, SavingOffice _bank) {
		bank = _bank;
		id = _id;
		start();
	}

	public void start() {
		flag = true;
		super.start();// 启动线程
	}

	public void setFlagValue() {// 设置为不转账状态
		flag = false;
	}

	public void run() {// 运行该线程
		while (flag) {
			int into = (int) (SavingOffice.num_accounts * Math.random());
			int amount = (int) (1000 * Math.random());
			bank.transfer(id, into, amount);
			yield();
		}
	}
}

 

  实例235 门锁打不开了(死锁)

  实例236 门锁终于被打开了(解决死锁) 

package Chapter17;

public class DoorOpen {
	static String[] keys = new String[] { "第1把钥匙", "第2把钥匙" };

	static class DoorKey1 extends Thread { // 静态内部类
		public void run() {
			synchronized (keys[0]) { // 在同一时间只能有一个类访问
				System.out.println("我拿起了" + keys[0] + ",在等着朋友用" + keys[1]
						+ "开防盗门");
				try {
					Thread.sleep(100); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				synchronized (keys[1]) {
					System.out.println("我又拿出来" + keys[1] + "打开了防盗门");
				}
			}
		}
	}

	static class DoorKey2 extends Thread { // 静态内部类
		public void run() {
			synchronized (keys[0]) {
				System.out.println("\n朋友拿出了" + keys[0] + ",在等待我用" + keys[1]
						+ "开防盗门");
				try {
					Thread.sleep(100); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				synchronized (keys[1]) {
					System.out.println("朋友又拿出了" + keys[1] + "打开了防盗门");
				}
			}
		}
	}

	static class GoWrong extends Thread { // 静态守护线程类
		public GoWrong() {
			this.setDaemon(true); // 线程设置守护
		}

		public void run() {
			while (true) {
				try {
					Thread.sleep(1000); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				System.out.println("守护线程:程序正在运行...");
			}
		}
	}

	public static void main(String[] args) { // java程序主入口处
		DoorKey1 one = new DoorKey1(); // 实例化对象
		DoorKey2 two = new DoorKey2();
		GoWrong daemon = new GoWrong();
		one.start(); // 启动线程
		two.start();
		daemon.start();
	}

}

 

  实例237 一个死锁的例子

package Chapter17;

import java.awt.*;
import java.awt.event.*;

public class DeadLock extends Frame {
	protected static final String[] names = { "One", "Two" };// 创建一个字符串数组,用于存放线程的名字

	private int accounts[] = { 1000, 1000 };// 存入账号

	// 创建TextArea组件
	private TextArea info = new TextArea(5, 40);

	private TextArea status = new TextArea(5, 40);

	public DeadLock() {// 构造方法
		super("致命的死锁!");// 调用父类Frame的带参构造方法
		this.setLayout(new GridLayout(2, 1));
		add(makePanel(info, "账号"));
		add(makePanel(status, "线程"));
		validate();
		pack();
		show();
		// 创建DeadLockThread对象
		DeadLockThread A = new DeadLockThread(0, this, status);
		DeadLockThread B = new DeadLockThread(1, this, status);
		this.addWindowListener(new WindowAdapter() {// 添加单击事件监听
					public void windowClosing(WindowEvent e) {
						System.exit(0);
					}
				});
	}

	public synchronized void transfer(int from, int into, int amount) {// 转账
		info.append("\n帐户 One:$" + accounts[0]);// 将给定文本追加到文本区的当前文本
		info.append("\n帐户 Two:$" + accounts[1]);
		info.append("\n>=$" + amount + "从" + names[from] + "到" + names[into]);
		while (accounts[from] < amount) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			accounts[from] = amount;
			accounts[into] = amount;
			notify();
		}
	}

	private Panel makePanel(TextArea ta, String title) {// 创建面板,按选择的布局方式将组件进行布局
		Panel p = new Panel();
		p.setLayout(new BorderLayout());
		p.add("North", new Label(title));
		p.add("Center", ta);
		return p;
	}

	public static void main(String[] args) {// 本程序的主方法
		DeadLock dl = new DeadLock();
	}
}

class DeadLockThread extends Thread {// 死锁线程
	private DeadLock dl;

	private int id;

	private TextArea display;

	public DeadLockThread(int _id, DeadLock _dl, TextArea _display) {
		dl = _dl;
		id = _id;
		display = _display;
		start();
	}

	public void run() {
		while (true) {
			int amount = (int) (1500 * Math.random());
			display.append("\nThread" + DeadLock.names[id] + "将 $" + amount
					+ "存入" + DeadLock.names[(1 - id)]);
			try {
				sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			dl.transfer(id, 1 - id, amount);
		}
	}
}

 

 

分享到:
评论

相关推荐

    Java范例大全 源码

    其次,《Java范例大全》还讲解了XML开发、Java图形编程、Java网络编程、多媒体开发、邮件开发、Java Web开发和Java安全等大量极其重要的企业级开发知识,使全书上升到一个新的高度;最后,以一个极具代表性的综合...

    Java范例开发大全

    《Java范例开发大全》共22章,内容涉及Java开发环境的搭建、Java基础类型与运算符、条件控制语句、异常处理、数组、字符串、输入输出流、面向对象及其四大特征、内部类与接口、Java常用类、集合、多线程编程、Java...

    JAVA多线程设计模式_中国铁道出版社_源码

    JAVA多线程设计模式_中国铁道出版社 本书浅显易懂的介绍了JAVA线程相关的设计模式,通过程序范例和UML图示来一一解说,书中代码的重要部分加了标注以使读者更加容易理解,再加上图文并茂,对于初学者还是程序设计...

    java多线程编程源码范例和详细说明(由浅入深,深度解读在资料后半部分).docx

    java多线程编程源码范例和详细说明(由浅入深,深度解读在资料后半部分)

    JAVA 范例大全 光盘 资源

    JAVA 范例大全 光盘 资源 书籍目录: 前言. 第1章 开发环境搭建 1 实例1 下载、安装并配置JDK 1 实例2 第一个Java程序 3 实例3 在Eclipse中创建第一个Java程序 4 常见问题 javac不是内部或者外部命令 6 常见...

    java范例开发大全(pdf&源码)

    第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223 参赛者的比赛生活(线程休眠唤醒) 407 实例224 资源搜索并下载(线程等待和通报) 410 实例225 模拟淘宝...

    Java编程宝典(十年典藏版).明日科技 李忠尉 陈丹丹 张振坤编著.源代码(完整版)

    其中第1篇为技能学习篇,主要包括java初体验、eclipse与netbeans、基本语法、控制流程语句、数组、类与对象、字符串、继承与多态、接口与抽象类、集合与异常处理、io流、tcp与udp技术、窗体程序开发、多线程技术、...

    java范例开发大全源代码

    第1篇 Java编程基础  第1章 Java开发环境的搭建(教学视频:9分钟) 2  1.1 理解Java 2  1.2 搭建Java所需环境 3  1.2.1 下载JDK 3  1.2.2 安装JDK 4  1.2.3 配置环境 5  1.2.4 测试JDK配置...

    java范例开发大全

    第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223 参赛者的比赛生活(线程休眠唤醒) 407 实例224 资源搜索并下载(线程等待和通报) 410 实例225 模拟淘宝...

    Java范例开发大全 (源程序)

     第13章 多线程编程(教学视频:121分钟) 405  13.1 多线程的五种基本状态 405  实例222 启动线程 405  实例223 参赛者的比赛生活(线程休眠唤醒) 407  实例224 资源搜索并下载(线程...

    Java范例程序1.rar_源码

    java的一些关于简单实例的运算及其编程,包括applet,多线程等

    Java范例开发大全(全书源程序)

    第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223 参赛者的比赛生活(线程休眠唤醒) 407 实例224 资源搜索并下载(线程等待和通报) 410 实例225 ...

    java源码包---java 源码 大量 实例

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java开发技术大全(500个源代码).

    ThreadImRunnable.java 继承Runnable接口实现多线程 mulThread.java 创建多个线程对象的类 demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类...

    JAVA上百实例源码以及开源项目源代码

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java编程技巧

    其中第1篇为技能学习篇,主要包括Java初体验、Eclipse与NetBeans、基本语法、控制流程语句、数组、类与对象、字符串、继承与多态、接口与抽象类、集合与异常处理、IO流、TCP与UDP技术、窗体程序开发、多线程技术、...

    java源码包4

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包3

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包2

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java教程.rar

    XianCheng2.java 基于多线程的例子 第11章 示例描述:介绍并演示AWT的使用。 FrameEx.java 建立空窗口的程序 FlowLayoutEx2.java FlowLayout的使用 第12章 示例描述:介绍并演示Swing组件的使用。 ...

Global site tag (gtag.js) - Google Analytics