- 浏览: 123173 次
- 性别:
- 来自: 佛山
文章分类
最新评论
-
zgw06629:
多谢提供的安装包
MyEclipse安装资源文件支持中文插件编辑属性 -
lmzpp:
学习了,谢谢
MyEclipse安装资源文件支持中文插件编辑属性 -
nba:
不错, 谢谢了
MyEclipse安装资源文件支持中文插件编辑属性 -
CMShmily:
MyEclipse安装资源文件支持中文插件编辑属性
第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范例 十九) 多媒体与图像处理 (二)
2011-09-30 19:27 1622图像处理 实例354 在计算机内存中创建一个图像 i ... -
JAVA范例 十九) 多媒体与图像处理
2011-09-30 18:40 1457a多媒体 实例349 测试音频播放器 import j ... -
JAVA范例 - Applet小应用程序
2011-09-30 18:27 3268Applet小应用程序 实例337 不断变大的文字 ... -
JAVA范例 十七)界面-Swing(二)
2011-09-30 18:06 1391实例326 BorderLayout版面布局 imp ... -
JAVA范例 十七)界面-Swing(一)
2011-09-30 17:51 2149实例306 JFrame框架的应用 import j ... -
JAVA范例 十六)数据库技术
2011-07-21 20:16 1624数据库技术 实例293 加载JDBC驱动程序 ... -
JAVA范例 十五)网络编程
2011-07-21 17:38 140115.1 IP地址 实例270 获 ... -
JAVA范例 十四)泛型
2011-07-21 17:30 1168第14章 泛型 14 ... -
JAVA范例 十三)多线程编程(3)
2011-07-21 17:12 1561线程应用实例 实例244 下雪的村庄 ... -
JAVA范例 十三)多线程编程(2)
2011-07-21 17:06 120613.3 线程的优先级 实例238 排座位(线程优 ... -
JAVA范例 十二)Java高级开发技术
2011-07-21 13:55 142312.1 Set 实 ... -
JAVA范例 十一)JAVA常用类
2011-07-21 13:34 138511.1 数学Math类 实例186 求圆周率∏值 ... -
JAVA范例 十) 内部类与接口
2011-07-21 12:30 1048内部类与接口 10.1 成员内部类 ... -
JAVA范例 九)面向对象---面向对象的四大特征
2011-07-21 11:50 17189.1 抽象 实例 ... -
JAVA范例 八)面向对象---面向对象的设计模式、垃圾回收
2011-07-21 11:43 9768.3 面向对象的 ... -
JAVA范例 八)面向对象---类、成员变量和方法
2011-07-21 11:30 1731类 实例148 简单的通讯录类 p ... -
JAVA范例 七)输入/输出流---字符流
2011-07-21 02:40 2180字符流 实例140 按顺序创建文件 ... -
JAVA范例 七)输入/输出流---字节流
2011-07-21 02:28 19927.2 字节流 实例123 复制指定目录下的文件 ... -
JAVA范例 七)输入/输出流---文件和目录
2011-07-21 02:16 1733文件和目录 实例116 ... -
JAVA范例 六)字符串---StringBuffer
2011-07-21 02:12 1431字符串缓存类StringBuffer ...
相关推荐
Java 多线程编程源码范例和详细说明 Java 多线程编程是一种能够同时执行多个任务的技术,可以提高程序的并发性和响应性,使得程序能够更好地利用 CPU 资源。本文将通过一个简单的 Java 多线程编程示例,向读者介绍...
在Java编程语言中,多线程是并发执行多个任务的核心机制。这个压缩包中的文件提供了几个关于Java多线程交互的实例,可以帮助我们深入理解如何在并发环境中控制线程的同步,确保数据的一致性和安全性。 首先,让我们...
4. **多线程**:Java提供了内置的多线程支持,如Thread类和Runnable接口。通用范例可能会包含线程同步、锁机制(如synchronized关键字、ReentrantLock等)、并发工具类(如ExecutorService、CountDownLatch、...
总的来说,《JAVA多线程教学演示系统》这篇论文不仅是对JAVA多线程技术的理论探讨,更是一个实践与教学相结合的优秀范例,对于提升学生的多线程编程能力具有很高的参考价值。VB图书管理系统论文范文虽不在本文讨论...
在Java编程语言中,多线程是其核心特性之一,它允许程序同时执行多个任务,提高了应用程序的效率和响应性。...学习这个示例有助于理解和掌握Java多线程编程,为实际项目开发中的并发处理打下坚实基础。
其次,《Java范例大全》还讲解了XML开发、Java图形编程、Java网络编程、多媒体开发、邮件开发、Java Web开发和Java安全等大量极其重要的企业级开发知识,使全书上升到一个新的高度;最后,以一个极具代表性的综合...
《Java范例开发大全》共22章,内容涉及Java开发环境的搭建、Java基础类型与运算符、条件控制语句、异常处理、数组、字符串、输入输出流、面向对象及其四大特征、内部类与接口、Java常用类、集合、多线程编程、Java...
- 多线程编程:通过Thread类或Runnable接口创建线程,理解同步机制如synchronized关键字、wait/notify机制。 - 异常处理:学习如何使用try-catch-finally语句块,以及自定义异常类。 - IO流操作:掌握字节流、...
【大漠多线程范例源码】是一个关于多线程编程的实例集合,由知名IT专家"大漠"提供,旨在帮助开发者深入理解和实践Java或其他编程语言中的多线程技术。多线程是现代软件开发中不可或缺的一部分,特别是在并发处理、高...
JAVA多线程设计模式_中国铁道出版社 本书浅显易懂的介绍了JAVA线程相关的设计模式,通过程序范例和UML图示来一一解说,书中代码的重要部分加了标注以使读者更加容易理解,再加上图文并茂,对于初学者还是程序设计...
综上所述,"Java多线程下载器范例"涉及了Java多线程编程、文件I/O操作、线程同步和通信、下载策略等多个核心概念。通过理解和实践这些知识点,开发者可以构建出高效、稳定的文件下载工具。在实际项目中,这样的下载...
2. **多线程编程**:解释了线程的创建、同步机制(如synchronized关键字、wait()、notify()方法)以及线程池的使用。 3. **IO流与NIO**:对比分析了传统IO和NIO的区别,讲解了文件操作、网络通信等场景下的IO应用。 ...
多线程编程也是Java的一大特色。通过实现Runnable接口或继承Thread类,可以创建并运行多个线程。在并发编程中,锁、同步机制、并发容器(如ConcurrentHashMap)等工具用于保证线程安全。源代码会展示如何编写并发...
《Java范例大全》源代码是一份非常宝贵的资源,它包含了大量的Java编程示例,旨在帮助开发者深入理解和掌握Java语言的各种特性和用法。这份源代码不仅覆盖了基础语法,还包括了面向对象编程、异常处理、集合框架、多...
6. **多线程**:Java支持并发编程,范例可能包含线程的创建、同步、线程池的使用等。理解如何在多线程环境下协调任务执行,是构建高性能应用程序的关键。 7. **反射机制**:Java的反射机制允许在运行时动态访问类的...
《Java范例开发大全源程序(下)》是针对Java编程语言的一份宝贵资源,包含了从第12章到第22章的丰富实例代码,旨在帮助开发者深入理解和掌握Java的各项核心特性。这份资料涵盖了广泛的Java编程主题,包括但不限于...
6. **多线程**:线程的创建(通过Thread类或实现Runnable接口)、线程同步(synchronized关键字、wait()和notify()方法)、线程池和并发工具类。 7. **反射**:动态获取类信息,创建对象,调用方法,以及修改私有...
在21-40.zip中,我们可能会看到异常处理、多线程、集合框架(如ArrayList和HashMap)以及输入/输出流的使用。41-60.zip和61-80.zip可能涉及到更深入的面向对象编程,包括接口、抽象类、枚举以及反射等特性。81-101....
《JAVA 范例开发大全 源代码》是一本为Java开发者提供的宝贵资源,它包含了近1000个可运行的Java类,涵盖了Java编程的各个方面。这些源代码实例旨在帮助读者深入理解Java语言的特性和用法,通过实践来提升编程技能。...
7. **多线程编程**:Java内置了多线程支持,通过实现`Runnable`接口或继承`Thread`类创建线程。理解并发控制(如`synchronized`关键字、`Lock`接口)和线程同步机制(如`wait()`, `notify()`, `notifyAll()`)是Java...