MVC
MVC含义
一种软件构架,简单的说就是在做软件的时候,可以将软件分为不同的模块,不同的模块实现了不同功能。
MVC 组成部分
Model 模型
View 视图
Controller 控制器
MVC就是三种组成部分的缩写。
MVC 不同模块的功能
Model(模型层) 程序员编写程序应用的功能,数据库设计等。属于后台操作。
View (视图层) 前台界面,也就是用户可以看到的图形见面,一般在web中是一些*.jsp或*.html。
Controller(控制器) 处理前台和后台请求。
MVC 优点
采用MVC的优点太多了,说再多不如你在真正的项目中自己体会,在这里不做太多解释。
MVC 包结构
虽然,这并不能说明所有MVC框架所有的包模式,不过我觉得新手对于这个包结构还是比较容易接受的。
DAO 模式
在DAO层,最主要的作用是:完成数据的操作。在这层,你可以完成对任何表的数据操作,不过个人认为DAO层最大的作用是简单了编程人员的编程逻辑,简单的说就是将一个大的问题,分成了几个比较小的问题,这样不管在测试还是在维护都起着很大的方便。
Factory 工厂
Factory 工厂在这里也可以说成是DAO的工厂,这里Factory仅仅产生了DAO。那么Factory工厂模式有什么好处呢?
在MVC中的Factory 层,你完全可以把它想象成现实中的工厂,生产某些东西,如果在程序中使用工厂模式,你可以简化编程代码,相当与现实中你需要某个产品不需要自己去生产,完全可以去工厂“拿”一个,这样程序的编程更加符合现实中的逻辑。
MVC 总结
本节,我仅仅是将MVC的编辑思想简单的介绍了一下,我没有加入一些详细的例子,因为我觉得你在接触MVC的时候,最好先了解MVC的编程思想,如果你要了解MVC的编程思想之后,你再接触MVC的编程时,你就会觉得特别简单。
最后,希望我这篇文章可以让大家简单的了解MVC的编程模式。
posted @
2011-01-25 09:30 tovep 阅读(2120) |
评论 (9) |
编辑 收藏
摘要: ForEach小结
<c:forEach>标签具有以下一些属性:
var:迭代参数的名称。在迭代体中可以使用...
阅读全文
posted @
2011-01-24 08:37 tovep 阅读(2347) |
评论 (0) |
编辑 收藏
通过以下Servlet程序和web.xml来说明web.xml的配置以及过程
创建一个Login的HTML文件
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>login.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="
test1" method="
post">
<table border="0" width="379" height="79">
<tr>
<td>帐号:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="5" align="center"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
以上HTML标签中要说明的是:
<form>标签中的
action="test_Web_xml" 和 method="post" 分别定义了Html将登陆的信息发送给了谁,以及发送信息的方法!
创建一个Servlet程序
public class LoginServlet extends HttpServlet{
public void
doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = null;
username = request.getParameter("username");
String password = null;
password = request.getParameter("password");
if(username.equals("username")&&password.equals("password")){
request.getRequestDispatcher("成功登陆!!!").forward(request,response);
}else{
request.getRequestDispatcher("登陆失败!!!").forward(request,response);
}
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>
Login
</servlet-name>
<servlet-class>
com.rise.LoginServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
Login
</servlet-name>
<url-pattern>
/test1
</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
我理解web.xml的作用就是将页面和后台程序正确连接!!!
通过一张图片说明我理解的web.xml的作用
以上的内容是我自己对web.xml的理解,我觉得很简单,但真正写程序的时候部署程序是非常复杂的!
posted @
2010-12-11 20:43 tovep 阅读(6289) |
评论 (2) |
编辑 收藏
什么是JDBC
JDBC是由一组Java语言编写的类和接口组成,用来处理关系数据库!利用JDBC的API,可用Java语法去访问各种各样的SQL数据库。
个人认为:
把JDBC当做是一门连接Java程序连接数据库的技术不如把JDBC当做连接程序和数据库的桥梁。
以下我要写的例子是用纯Java的Driver来连接数据库的方式。连接的数据库是mysql。
JDBC编程步骤
1.加载数据库驱动(jar文件)
//需要下载一个数据库的jar包,并导入相应的JDBC项目中,创建路径!
Class.forName("com.mysql.jdbc.Driver");
2.获得数据库连接
DriverManager.getConnection("jdbc:mysql://Database_IP:3306/DATABASE","DATAROOT","PASSWORD");//返回Connection————获得数据库连接
3.创建语句
String sql = "SQL_TORUNNING";
向DATABASE发送一个执行语句
Statement stmt = conn.createStatement();//创建一个 Statement 对象来将 SQL 语句发送到数据库.
Statement—————SQL_RUNNING!!!
4.执行查询
ResultSet rs = Statement.executeQuery(SQL_RUNNING);//执行SQL_RUNNING命令,返回ResultSet
//如果执行的数据库语句不是对数据库中的内容进行修改的话,则用 Statement.executeQuery()
//如果执行的数据库语句是修改数据库中的内容进行修改的话,则用 Statement.executeUpdate()
//当然他们返回值的类型也不同!
//根据命令的不同Statement的方法也不同
创建一个表
Statement.execute(create a table)
增删改查Insert、update、delete...
Statement.executeUpdate()
查询语句Select
Statement.executeQuery(Select);
5.遍历结果集
while(ResultSet.next()){
ResultSet.getInt(int);
ResultSet.getString(int);
......
}
6.关闭数据库连接
Connection.close();
步骤分析
(图一)
1.加载数据库驱动
我们来看图一,工厂和几个农村之间有一条河,不能够直接进行沟通,工厂就相当于一个Java程序,而几个农村就相当于不同的数据库;
工厂为B村生产一些材料,但是生产出来之后并不能直接交给B村,然后工厂的厂长就想在工厂和B村之间架设一座桥梁来运送生产出来的材料——我们大可把数据库驱动加载当做这个架设桥梁的想法。
在程序中我们要怎么做呢?
在加载数据库驱动的时候,必须要将相应的mysql-connector-java-5.0.4-bin.jar包,然后将jar包导入相应的项目中如下图
在mysql-connector-java-5.0.4-bin.jar右击建立路径,就相当于import的过程——我不确定这么说对不对,但我是这么理解的。
建立路径后,你的项目将出现一个新的文件,如下图
这样的话,你就可以顺利加载数据库驱动,否则当你在运行的时候会出现找不到Driver.class的异常,也就是无法加载数据库驱动。
Class.forName("com.mysql.jdbc.Driver");
2.获得数据库连接
既然厂长有想法和B村之间架设一座桥梁,那就要和B村商量一下啊!然后,厂长就要去河的对岸,那条河呢?就是在工厂和B村之间的那条河(这条河就相当于Database_IP),然后去找B村的村长(在这里要明白是B村的村长不是A村的,所以不能找错了!!!),找到B村村长,“我要在工厂和B村之间建设一座桥,来运输我们的东西”,下一步谈的当然是条件了,工厂老板说“我要B村出资90%,剩下的由工厂出!!”村长当然不干了,这桥当然也就没法建设了!!!所以只有当两者都满意的情况下才可以建设桥梁(比如,各处50%)其实谈条件的过程就相当于验证数据库的"DATAROOT"和"PASSWORD"!!!只有两者都正确的情况下才可以进行下一步的计划——也就是建设桥梁!!!
在程序中的过程如下:
Connection conn = null;
conn = DriverManager.getConnection("jdbc:mysql://Database_IP:3306/DATABASE","DATAROOT","PASSWORD");
//返回Connection————获得数据库连接
3.创建语句
桥已经建好了,然后工厂要准备一些卡车来运输生产的货物,然后农村需要根据不同的货物来处理这些货物,有些货物直接卸在B村就可以了,但有些货物卸在B村之后,B村要做一些处理然后运回工厂!!!
这个过程在程序是怎么体现的呢?
String sql = "SQL_TORUNNING";
向DATABASE发送一个执行语句
Statement stmt = conn.createStatement();//创建一个 Statement 对象来将 SQL 语句发送到数据库.
Statement—————SQL_RUNNING!!!
4.处理数据库发送来的消息
如果工厂运输到B村的货物,只要B村的村长给工厂开一张条就行了;但也会有一些货物需要运回工厂!!
在程序中:
ResultSet rs = Statement.executeQuery(SQL_RUNNING);//执行SQL_RUNNING命令,返回ResultSet
//如果执行的数据库语句不是对数据库中的内容进行修改的话,则用 Statement.executeQuery()——需要返回一些货物
//如果执行的数据库语句是修改数据库中的内容进行修改的话,则用 Statement.executeUpdate()——开张条就行了
//当然他们返回值的类型也不同!
//根据命令的不同Statement的方法也不同
创建一个表
Statement.execute(create a table)
增删改查Insert、update、delete...
Statement.executeUpdate()
查询语句Select
Statement.executeQuery(Select);
5.处理数据库传回的内容
这个过程由工厂完成,如果是返回的一些货物的话,工厂要做一些处理。
处理的过程:
while(ResultSet.next()){
ResultSet.getInt(int);
ResultSet.getString(int);
......
}
6.关闭数据库
这样的话,工厂和B村的交易就完成,在现实世界中工厂和B村之间的桥梁不会被拆除,因为建一座桥的代价很大,但在程序和数据库之间架设一座桥梁简直太简单了,所以在这里我们要把这座桥梁拆除。
Connection.close();
简单的举了一个例子来说明数据库和程序之间是怎么连接的,望对大家有所帮助。
posted @
2010-12-09 18:37 tovep 阅读(1617) |
评论 (1) |
编辑 收藏
SQL语言是操作数据库的基础语言,对于不同的数据库语言产品,SQL语言大多是通用的,本篇博客旨在介绍一些最常用的SQL语句。希望对大家能有所帮助。
注:
本文中的红色字体黄色背景的内容为SQL语句!!
笨人也是菜鸟,如果我写的有错误,大家一定要指出来啊!!!好了,废话不说了,切入正题:
首先,使用
status查看MySQL当前的信息
1.使用
show databases;语句查看当前数据库:
2.使用
create database DATABASE_NAME;语句来创建DATABASE_NAME数据库
这样,我们创建好了一个名字为database_name的数据库。
注:数据库语句对字母大小写不敏感!
3.使用
use DATABASE_NAME;切换到使用DATABASE_NAME数据库模式。
4.在database_name数据库创建一个表:
create table if not exists table_name -- 如果表table_name不存在则创建
(id int primary key auto_increment, -- 创建int类型为主键,且自动增长
name varchar(200) not null, -- 创建字符类型的列,最大长度是200字节
age int(3), -- 创建int类型,长度为3个字节
sex varchar(2), -- 创建字符类型,长度是2个字节
salary float(11,2), -- 创建float类型的列,长度为2个字节
address varchar(50), -- 创建字符类型,长度为50个字节
birthday date -- 创建日期类型
);
这样就创建好了一张表,可以用 describe 或则 desc来查看表的结构
describe table_name;
desc table_name;
这样数据就创建好了一张表,我们可以用
show tables; 来查看数据库中所有表
然后,我们就可以看见我们创建的表
====================================================================================
数据库最具核心的用法——对数据库表的数据的
增删改查。
向表中增加数据(要了加入表的结构,看哪项可以为空)
insert table_name (name,age,sex) values ('tovep',22,'男');
向表中加入数据的时候,并不是要把所有的信息都要写近期,只要表中结构设置为可以为空的都
可以不写!!
id不用写,因为它是自动增长的!
要想查看表中的内容,可以用select语句———为了说明下面的情况,我加入了多条信息
select * from table_name; -- 将table_name表中的所有数据都打印出来
select name from table_name; --查看所有人的名字
select * from table_name where id<5; --将表中id小于100的都打印出来
在使用select 语句查询的时,常常用到别名
select t.name,t.id,t.age from table_name as t;
select 语句中的where表示查询的条件
where中还可以使用like与"%"对字符类型的列进行模糊查询
select * from table_name where name like 't%';
update语句:修改数据
update 表名 set 字段名 = '修改的值'
update table_name set name='tvoep1' where id>2;
删除用
delete from 表名 where 判断信息
delete from table_name where id=5;
这样的话就删除了id=5的信息
====================================================================================
使用drop 来删除表或者数据库
drop table table_name;
drop database database_name;
posted @
2010-12-06 11:04 tovep 阅读(2293) |
评论 (2) |
编辑 收藏
经过一个多月的Java学习,我们慢慢深入了解了Java中的一些比较高级的方法!但这些方法在你调试的时候一定要慎重!!不要等待失去了整个硬盘,才后悔莫及!!! 如果你在编程的时候多长个心眼,这些小的错误是可以避免的!!!
下面我们来看一下一个让人很崩溃的错误,这个错误让我感到不可思议!!代码如下:
import java.io.File;
public class KillBackServer {
public static void main(String[] args){
File f = new File("C:\\");
fun(f);
}
//定义一个静态函数,用来实现对一盘文件的遍历
public static void fun(File f)
{
if(f.isDirectory())
{
File file[] = f.listFiles();
try
{
for(int i = 0 ; i <file.length ; i++)
{
fun(file[i]);
}
}
catch(Exception e){}
}
else
{
if("我是病毒.exe".equals(f.getName()))
System.out.println(f);
//仅仅当程序找到"我是病毒.exe"的 时候才执行这一句代码
//f.delete();
System.out.println("该病毒已被查杀");}
System.out.println(f.getPath() + "***********************");
}
}
}
大家一定要注意红色字体的代码!!!我之所以注释了,就是怕直接复制我的代码,然后运行……
如果这样后果你是知道的……
本来这段代码是用来扫描C盘,找到"我是病毒.exe"文件,并把它删除,判断一个文件名,用的是equals这是对的!!!
错就错在:if()判断,大家都明白了吧!
希望大家以后不要因为犯了这个低级错误,而把自己的硬盘给了格了= = |||
其实,有很多方法可以避免这种错误!!!比如,你可以在f.delete(); 后面加上一句打印语句,这样的话,在你测试的时候就会发现,原来if语句后面少一个大括号……
这个错误写出来仅仅为了提醒大家规范的重要性!!!
posted @
2010-11-17 21:29 tovep 阅读(2658) |
评论 (16) |
编辑 收藏
/**
* Robot类 :
*
* exec 函数声明:
* public Process exec (String command) throws IOException ,参数及功能说明:
* command: 一条指定的系统命令
* 功能:在单独的进程中执行指定的字符串命令
*
* keyPress 函数说明:
* public void keyPress(int keycode),参数及功能说明:
* keycode:要按下的键(例如,KeyEvent.VK_A)
* 功能:模拟按下指定键
*
* keyRelease 函数说明:
* public void keyRelease(int keycode),参数及功能说明:
* keycode:要释放的键
* 功能:模拟释放指定键
*
* @param tovep
*/
import java.awt.Robot;
import java.awt.event.KeyEvent;
public class Exce {
public static void main(String[] args) {
try{
//创建自动操作类
Robot robot = new Robot();
/**
*
* 利用Runtime类运行Word程序的方法为:
* Runtime.getRuntime().exec("cmd /c start winword");
* 括号里的是系统命令
*
*/
//启动记事本程序
Runtime.getRuntime().exec("cmd /c start notepad");
//延缓几秒钟,等待记事本程序启动成功
robot.delay(3000);
//模拟按下"Ctrl + Space" 组合键,启动输入法
pressKeyWithCtrl(robot,KeyEvent.VK_SPACE);
//模拟随机按下100个字母,输入汉字
for(int i=0;i<100;i++){
pressKey(robot, (int) (Math.random()* 25) + 'A');
pressKey(robot,KeyEvent.VK_SPACE);
}
//延缓5秒钟,一共观察
robot.delay(5000);
//关闭记事本
//closeApplication(robot);
}catch (Exception e){
System.out.println(e.getMessage());
}
}
//模拟按下键盘字符键
public static void pressKey(Robot robot, int keyvalue){
//模拟按下
robot.keyPress(keyvalue);
//模拟弹起
robot.keyRelease(keyvalue);
}
//模拟同时按下"Ctrl"键和字符键
public static void pressKeyWithCtrl(Robot robot, int keyvalue){
//模拟按下
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(keyvalue);
//模拟弹起
robot.keyPress(keyvalue);
robot.keyRelease(KeyEvent.VK_CONTROL);
}
//模拟按下"Alt + F4"组合键,关闭当前应用程序
public static void closeApplication(Robot robot){
//模拟按下"Alt + F4"组合键
//模拟按下
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_F4);
//模拟弹起
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_F4);
//模拟按下"N",不保存文件退出记事本程序
//模拟按下
robot.keyPress(KeyEvent.VK_N);
//模拟弹起
robot.keyRelease(KeyEvent.VK_N);
}
}
posted @
2010-11-17 00:14 tovep 阅读(5405) |
评论 (1) |
编辑 收藏
在Java中,Everything is Object!所以在文件中,要不例外!
在Java中,可以用File类来表示一个文件!!!(注意这里的文件可以是所有文件,包括文件夹)
下面的代码表示一个文件:
public class Demo {
public static void main(String[] args){
File f = new File("e:\\file");
if(f.isDirectory()){
System.out.println(f.getPath());
}
}
}
运行结果是:
代码中isDirectory()方法是判断文件是文件夹还是一个文件(这里可能有点迷糊),也可以这么理解,我所说的文件夹就是一个目录,
getPath()方法是打印文件(这里指的是file文件夹)的路径!!!
看看下面的代码还有注释:
/**
*
* File.speparator的作用是判断在不同的系统中斜杠的方向
*
* 在windows中斜杠的方向是向右斜的\\
* 在Linux 中斜杠的方向是向左斜的//
*
*
* File中createNewFile方法:
* 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
* 检查文件是否存在,若不存在则创建该文件,这是单个操作,对于其他所有可能影响该文件的文件系统活动来说,该操作是不可分的。
*
* 注:此方法不应该 用于文件锁定,因为所得协议可能无法可靠地工作。应该使用 FileLock 机制替代。
*
*
*/
import java.io.File;
public class Demo01 {
public static void main(String[] args) throws Exception{
File f;
f = new File("e:" + File.separator + "file" + File.separator + "io.txt");
System.out.println(f.createNewFile());
}
}
===================================
运行结果是:
大家注意,如果你的直接复制这些代码的话,可能会出现以下异常
看看大家都明白了吧! 系统找不到指定的文件,就是在e盘下新建一个file文件夹就可以啦!!!
下面代码详细的介绍了File类中的createNewFile()方法:
/**
*
* File中createNewFile方法:
* 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
* 检查文件是否存在,若不存在则创建该文件,这是单个操作,对于其他所有可能影响该文件的文件系统活动来说,该操作是不可分的。
*
* 注:此方法不应该 用于文件锁定,因为所得协议可能无法可靠地工作。应该使用 FileLock 机制替代。
* 返回:是布尔型
*
*/
import java.io.File;
public class Demo02 {
public static void main(String[] args) throws Exception{
File f = new File("f:\\demo.txt");
System.out.println(f.createNewFile());
}
}
运行结果如下:
下面介绍一下File类中delete()方法,代码如下:
/**
*
* 要操作一个文件,必须要找到这个文件
* 在Java中,只有File类能表示一个文件,所有用File表示一个文件
* File的属性就是文件的路径,虚拟机会根据File类的参数找到指定的文件
* 找到问及那后可以用File类的方法进行操作!
*
* delete()方法可以删除一个文件或者一个整个文件夹(整个目录),返回结果是布尔类型!!
*
* */
import java.io.File;
public class Demo11 {
public static void main(String[] args) {
File f = new File("f:\\demo.txt");
f.delete();
if(boo){
System.out.println("成功删除文件");
}
}
}
这个程序运行的结果:
下面的代码是介绍查看一个文件的目录,以及判断这个文件是否是文件夹,代码如下:
/**
*
* File的一个方法File.getPath()
* 是将此抽象路径名转换为一个路径名字符串。
*
* File的exists方法
* 是测试此抽象路径名表示的文件或目录是否存在。
*
*
* File的getParent()方法
* 是返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null
*
* */
import java.io.File;
public class Demo21 {
public static void main(String[] args) {
File f = new File("f:" + File.separator + "demo.txt");
System.out.println(f.getPath());
System.out.println(f.getParent());
if(f.exists()){
f.delete();
}
else{
try{
System.out.println(f.createNewFile());
}catch(Exception e){}
}
}
}
运行结果:
再看一个判断目录的方法:
/**
*
* File的一个方法File.getPath()
* 是将此抽象路径名转换为一个路径名字符串。
*
* File的isDirectory()的方法
* 是测试此抽象路径名表示的文件是否是一个目录。
* 当且仅当此抽象路径名表示的文件存在且 是一个目录时,返回 true;否则返回 false。
*
*
* */
import java.io.File;
public class Demo51 {
public static void main(String[] args){
File f = new File("f:" + File.separator + "aa");
System.out.println(f.getPath());
System.out.println(f.isDirectory());
}
}
运行结果:
注意下一个代码,可能对你很有帮助啊!!
/**
*
* File的list()方法可以:
* 返回一个字符串数组,
* 这些字符串指定此抽象路径名表示的目录中的文件和目录。
*
* */
import java.io.File;
public class Demo61 {
public static void main(String[] args) {
File f = new File("f:\\book");
//使用list列出
//列出的只是一个名称
String[] str = f.list();
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
}
}
这个程序的运行结果是你目录下的文件:
下面的程序 你可能会很感兴趣!因为你想玩HK,或者你想给别人整个恶作剧,你必须要扫描下他的电脑,以下方法就实现了怎样去扫描一个电脑里的所有文件(我的代码选择的是扫描C盘下的所有文件,如果你想扫描其他盘,只要把文件改一下就OK啦)
import java.io.File;
public class Demo81 {
public static void main(String[] args) {
String str = "C:\\";
File f = new File(str);
fun(f);
}
//要不断列出,因为给出的File类对象可能是一个目录
public static void fun(File f){
//判断给定的路径是否是目录,如果是目录在列出
if(f.isDirectory()){
File[] file = f.listFiles();
//再依次循环进行判断
try{
for(int i = 0;i < file.length;i++){
//继续把内容传入到fun方法之中进行验证
fun(file[i]);
}
}catch(Exception e){}
}
else{
System.out.println(f);
}
}
}
运行结果我就不贴出来了,因为C盘的文件太多啦!!!如果你想知道,自己把代码带下看看,你会很吃惊的!你会想原来扫描的原理这么简单!!!
posted @
2010-11-07 23:05 tovep 阅读(59622) |
评论 (2) |
编辑 收藏
Java线程类有两种实现方式,第一种就是继承Thread类,另一种是现实Runnable接口。这两种实现方式的区别很大,下面就说一下它们之间到底有什么区别。
我们首先用第一种方式写一个线程类:
代码如下:
package Ticket;
public class Extends {
public static void main(String[] args){
//实例化进程并准备执行
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
}
}
class MyThread extends Thread{
//定义一个变量
private int ticket = 10;
public void run(){
//这里之所以要循环300次,就是为了让所有的 车票都卖出去!可能你会想,为什么不是30呢?
//嘿嘿。。。聪明的你肯定明白这个循环的次数为什么会多出票数很多?=====其实我开始也不知道!!! ==|||
for(int i=0;i<300;i++){
try {
//调用sell()方法
this.sell();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sell(){
if(ticket>0){
System.out.println(Thread.currentThread().getName() + " ===> 还剩下" + (ticket--) + "车票");
}
}
}
看看这个程序的运行结果你就明白为什么继承Thread类实现线程类的一个弊端
------------------------------------------------
大家都发现了吧!输出的结果和预想的不一样!!!
我们来分析一下代码,查看main函数:
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
我们可以看出,实例化了三个MyThread类,这样的话,private int ticket = 10;就运行了三次,所以ticket打印出来的 也就是30张;在这里注意一下并不是ticket赋值为30,而是ticket赋值为10,但赋值了三次!!!也就是现在有三个ticket!!!
这样并不能实现资源共享!
我们知道我们利用多线程就是为了将多个线程去处理一个数据的集合!!! 他们是同时处理的!!!如果向上面的话,并没有将数据的集合(ticket)进行共享,而是将每一个类都从新建了一个数据的集合,分别对自己的集合进行处理!!!!
如果想解决这个问题,其实也很简单,不过如果当数据的类型和种类比较多的时候,这样写就太麻烦了!!!!
那实现Runnable接口的线程类可不可以呢!!???
下面来看一看:
代码如下:
package IO;
public class Inter {
public static void main(String[] args){
//声明并实例化一个MyThread01类
MyThread01 mt = new MyThread01();
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
}
}
class MyThread01 implements Runnable{
private int ticket = 10;
public void run(){
for(int i=0;i<200;i++){
try {
this.sell();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sell(){
if(ticket>0){
System.out.println(Thread.currentThread().getName() + " ===> 还剩下" + (ticket--) + "车票");
}
}
}
---------------------------------------------
这段程序的运行结果:
看看这个结果是不是和自己想的一样啊!!!这样就可以了!!!用这个方法去创建一个线程类是不是可以达到资源共享啊!!!
其实啊!我看来,所谓的资源共享也就是将一个数据的集合让多个线程去处理!!!
我们看一下代码!!!
MyThread01 mt = new MyThread01();
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
我们可以看出这个过程中,我们只声明并实例化了一个MyThread01类,也就是说在这里过程中,给ticket进行了初始化!!!
但大家要注意的是:真正创建处理数据的线程是
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
因此,这样可以将一个ticket的数据集 由三个线程来处理!!!
这样就是所谓的资源共享!!!
ok???
=====================================================================
总结一下这两种方式的特点:
1.继承Thread来创建线程类的方法,在继承了Thread后,不能再继承其他类,这样灵活性就不如实现Runnable接口来创建线程类的方法了!!!
2.正如上面所说的使用实现Runnable接口来创建线程类的方法可以达到资源共享!!!(在这里说明一下:继承Thread类来创建线程类的方法也可以实现资源共享,只不过比较麻烦!!!因此,在创建线程类的时候,应优先选择实现Runnable接口来创建线程类的方法!!!)
posted @
2010-11-07 20:30 tovep 阅读(5936) |
评论 (8) |
编辑 收藏