软帝集团培训第四周小结

第四周周报小结:感觉这一周过得是最快的,前两天复习了之前的线程和一些Java高级部分比较难懂得部分,复习了一些我们之前没有很明白的知识,让我们对之前的知识有了更加深刻地印象,然后就暂时结束了Java的学习,感觉之前学的很多都是听过去了,并没有太多的去回顾之前的知识,有一些还不是很懂得地方也没有回去消化,一是没时间,二十懒得去回顾,不过时间还会有的,主要是自己没有主动去想搞学习的意愿,再跟别的同学交流之后,别人感觉都很努力,我感觉还是要更加努力一点,比你优秀的人还比你努力,那我还有什么借口不去努力,以后回家还是每天都要看一会,熬过这四个月就好了,现在只有三个月了,周三周四讲了一些比较简单的数据库查询语句,感觉还是比较好懂的,周五柴佬没在,上午也不知道在干什么,下午又出去玩了,周六一晃就过去了,又放假了,这一周感觉像做梦一样的,过的是真的快,从下周起一定要每天回去都搞会学习,下周再来汇报情况吧,这就是我本周的小结。

 

 

本周学习内容:

线程并发

  多线程应用中如果涉及到多个线程操作共享变量,极有可能出现线程并发导

 

致数据不安全问题,例如银行账户取钱问题:

 

有一个银行账户,还有余额1100

 

元,现在A通过银行卡从中取1000元,而同时另外一个人B通过存折也从这个账

 

户中取1000元。取钱之前,要首先进行判断:如果账户中的余额大于要取的金

 

额,则可以执行取款操作,否则,将拒绝取款。

 

我们假定有两个线程来

 

分别从银行卡和存折进行取款操作,当A线程执行完判断语句后,获得了当前账

 

户中的余额数(1000元),因为余额大于取款金额,所以准备执行取钱操作(

 

从账户中减去1000元),但此时它被线程B打断,然后,线程B根据余额,从中

 

取出1000元,然后,将账户里面的余额减去1000元,然后,返回执行线程A的动

 

作,这个线程将从上次中断的地方开始执行:也就是说,它将不再判断账户中

 

的余额,而是直接将上次中断之前获得的余额减去1000。此时,经过两次的取

 

款操作,账户中的余额为100元,从账面上来看,银行支出了1000元,但实际上

 

,银行支出了2000元。

 

 

  账户类:Account.java

public class Account {

 

private String num; //账号

private double cash; //余额

 

public Account(String num,double cash) {

this.num = num;

this.cash = cash;

}

 

public String getNum() {

return num;

}

 

public void setNum(String num) {

this.num = num;

}

 

public double getCash() {

return cash;

}

 

public void setCash(double cash) {

this.cash = cash;

}

}

 

    取款线程类:

   /**

 * 用于完成取款操作的线程类

 * @author mrchai

 */

public class AccountManager implements Runnable{

 

private Account account; //需要被取款的账户

private double money; //需要取走金额

 

public AccountManager(Account account, double money) {

super();

this.account = account;

this.money = money;

}

 

@Override

public void run() {

//判断账户中的余额是否足够

if(account.getCash() >= money){

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

//减少账户的余额

account.setCash(account.getCash() -

 

money);

System.out.println

 

(Thread.currentThread()+"取款成功,余额:"+account.getCash());

}else{

System.out.println

 

(Thread.currentThread()+"取款失败,余额不足!");

}

}

   测试类Client.java

public class Client {

 

public static void main(String[] args) {

 

//创建账户类,余额10000

Account a = new Account("0001", 10000);

        //创建Runnable对象,每次取款10000

AccountManager am = new AccountManager(a, 10000);

 

Thread t1 = new Thread(am);

Thread t2 = new Thread(am);

//启动两个取钱线程

t1.start();

t2.start();

}

}

 结果:Thread[Thread-0,5,main]取款成功,余额:0.0

       Thread[Thread-1,5,main]取款成功,余额:0.0

 

根据结果显示,如果时间点恰到好处(两个线程同时进入查询,发现余额足够)

 

,两个线程都能成功取钱,这对银行就不公平(损失10000);

 

 

Synchronized

 

 

   以上问题就是线程并发共享变量时引起的数据结果不一致的问题;针对以上

 

的问题,可以通过同步块或者同步方法来解决,通过synchronized可以实现对指

 

定对象或者方法锁定,一旦锁定,则当前线程结束对该对象或该方法使用前其

 

他线程无法进行操作,从而确保数据同步。

 

-

      同步块:使用synchronized语句块锁定指定对象

-

      同步方法:在方法返回类型前使用synchronized关键字修饰

 

 

   死锁

   在多线程并发操作时,如果使线程同步,则极有可能造成死锁,死锁主要是

 

有多个线程在等待对方释放所占有的资源时引起,死锁无法解决只能尽量避免

 

 

UDP数据广播

    在通用的以太网(Ethernet)构架下,计算机于计算机之间的数据交换都是

 

通过交换机来完成的。如果一份数据需要被传送给多个接收者,在使用TCP/IP

 

连接的情况下,数据发送者需要向交换机发送N 个同样的拷贝,而交换机则负

 

责将这N 个拷 贝分发给所有的接收者;

 

 

    在使用UDP 数据广播的情况下,数据发送者只需要向交换机发送一个拷贝

 

,交换机负责将这个信息制作N 个拷贝发送给所有的机器。在这种情况下,使

 

用TCP/IP连接会大大的增加网络的负担。在一个普通局域网络中,可以认为由

 

于网络状况较差而造成数据丢失的可能性比较小,而利用UDP 数据广播进行 数

 

据交换能够大幅度减轻网络的负担 。

 

UDP数据广播核心类:

 

 

   - MulticastSocket

 

   - DatagramPacket

 

  

  广播发送

public class MulticastDemo {

 

public static void main(String[] args) throws IOException {

 

String msg = "本周五下午举办第一次班级过活动,望广大

 

童鞋积极参加,相互转告!!!!";

//创建组播地址对象

InetAddress ip = InetAddress.getByName("228.5.6.7");

        //创建数据广播通道对象

MulticastSocket ms = new MulticastSocket();

//将组播地址加入网络通道中

ms.joinGroup(ip);

 

//将消息内容打包成数据报包

DatagramPacket dp = new DatagramPacket(msg.getBytes

 

(),0, msg.getBytes().length, ip, 6789);

//发送数据广播

ms.send(dp);

ms.close();

}

}

 

接收广播

 

public class MulticastDemo_Receiver {

 

    public static void main(String[] args) throws IOException {

 

        InetAddress ip = InetAddress.getByName("228.5.6.7");

        MulticastSocket ms = new MulticastSocket(6789);

        //将组播地址加入网络通道中

        ms.joinGroup(ip);

 

        byte[] b = new byte[1024];

        //将消息内容打包成数据报包

        DatagramPacket dp = new DatagramPacket(b,b.length);

        ms.receive(dp);

        String s = new String(dp.getData(),0,dp.getLength());

        System.out.println(s);

    }

}

 

数据库内容:

mysql常用命令

 

系统命令

(以管理员身份运行)

 

 

#启动服务

net start mysql

#停止服务

net stop mysql

 

#进入mysql命令行

mysql -uroot -p123456

 

#退出mysql命令行

exit

 

#修改密码

mysqladmin -uroot -p123456 password root

 

 

Mysql常用命令

--显示数据库实例

show databases;

--创建数据库实例

create database mydb;

--使用数据库实例

use mydb;

--显示实例中所有数据库表

show tables;

 

SQL语句

 

 

结构化查询语言,一门关系型数据中通用的操作语言,语法结构类似英语口语

 

,sql语句通常划分为三类

 

 

- DDL

 

- DML

 

- DCL

 

 

DDL

/*

创建用户表,表中包含用户id,用户名,密码

*/

create table tbuser(

    id int,

    username varchar(10),

    password varchar(20)

);

 

--查看表结构

desc tbuser;

 

--向表中新增level列是int类型

alter table tbuser add level int;

 

--修改表中列的(将level列的名称改变为dengji)

alter table tbuser change level dengji int;

 

--删除表

drop table tbuser;

 

 

DML语句

--向表中插入一条数据

insert into tbuser(username,password) values('softeem','123456');

 

--批量插入数据

insert into tbuser values(1,'rose','666'),(2,'jack','8888'),

 

(3,'tom','999');

 

--蠕虫复制

insert into tbuser select * from tbuser;

 

--查询表中所有数据

select * from tbuser

 

--修改所有id为null的列为0

update tbuser set id=0 where id is null;

 

--修改多列数据

update tbuser set password='admin',username='admin' where id=1;

 

--删除id为0的所有数据

delete from tbuser where id=0;

 

 

约束

 

 

约束是维护数据完整型的一种操作,在数据库中维护数据完成性操作中包含以

 

下解决方案:

 

 

- 约束(contraint):最简单最容易实现的一种方式

 

- 存储过程(procedure)

 

- 触发器(trigger)

 

约束主要包含五大类:

 

 

1. 主键约束

 

2. 外键约束

 

3. 不为空约束

 

4. 唯一约束

 

5. 检查约束(mysql暂不支持)

 

 

--修改制定列设置列不为空

alter table user change username username varchar(16) not null;

 

--使用修改语句设置表的列为唯一列

alter table user add constraint uq_name unique(username);

 

外键约束

通过设置外键约束可以让当前一张表与另一张表产生约束关系,在执行更新操

 

作是,会通过约束的关系保证数据的完整性(被设置外键的列必须关联另一张表

 

的主键列)

 

数据库备份

 

备份

(系统命令行)

 

#备份数据库实例

mysqldump -uroot -proot mydb > d:/mydb.sql

 

#备份表

mysqldump -uroot -proot mydb tbuser > d:/tbuser.sql

 

auto_increment:设置列自增,可用于主键列以及非空唯一列(not null

 

unique)

 

 

unsigned:设置无符号列(列值不允许为负数)

 

 

zerofill:设置零填充列(当列数据长度不到定义长度时,数值前补0)

 

 

 char类型跟varchar类型区别   

char类型是定长字符串,默认大小是255(最大255);char类型一旦定义长度

 

,则无论实际添加的数据长度是否达到最大长度,都会将定义空间占满,char

 

类型效率高一般用于长度固定的列。

 

 

varchar类型是定长字符串,默认大小是255(最大长度取决与数据表的编码模

 

式,utf-8:65535/3;GBK:65535/2),varchar类型定义长度之后系统不会直

 

接分配对应大小的空间,而是根据实际填充值的长度申请空间,相对char类型

 

更节省空间,所以varchar用于长度不定的列

 

 

SQL查询

sql语句DML语句中最为复杂的是查询语句,insert,update,delete语句多数情

 

况为单表操作,但是select与可以关联多张数据表,针对sql查询需要明确三点

 

:

 

1. 查询列

 

 2. 查询目标表

 

 3. 查询条件

 

 

  SQL查询语法:

 

 

SELECT 查询列1,查询列2,... FROM 目标表

 

 

  【WHERE 查询条件】

 

 

 【GROUP BY 列名称】

 

 

【HAVING 查询条件】

 

 

 【ORDER BY 列名称 ASC|DESC】

 

 

【LIMIT [偏移行,]记录行数】

  

 

sql查询常见关键字:

 

 

  - from子句:指定查询数据的表

 

  - where子句:查询数据的过滤条件

  

- group by子句:对匹配where子句的查询结果进行分组

 

  - having子句:对分组后的结果进行条件限制

  

  order by子句:对查询结果结果进行排序,后面跟desc降序或asc升序(默认

 

)   

  

- limit子句:对查询的显示结果限制数目

 

 

  单表查询

--查询所有员工的姓名,职位,月薪

select ename,job,sal from emp;

 

--查询月薪超过10000的员工

select * from emp where sal>10000;

 

--查询入职时间在2017-01-01~2017-12-31之间的员工

select * from emp where hiredate between '2017-01-01' and '2017-12-

 

31';

 

--查询所有市场经理和项目经理信息

select * from emp where job in('市场经理','项目经理');

 

--模糊查询 ‘%’ ‘_’

--查询员工姓名中包含‘杰’的员工

select * from emp where ename like '%杰%';

--查询员工中所有的‘张’姓员工

select * from emp where ename like '张%';

--查询员工中‘周’姓名字只有两个字的员工

select * from emp where ename like '周_';

 

--聚合函数:count() max()  min() sum() avg()

--查询出emp表中的总记录行数

select count(*) from emp;

--查询出emp表中的最高/低薪资 max/min

select max(sal) from emp;

--统计一个月需要支出的共工资?

select sum(sal) from emp;

--统计1号部门的平均薪资?

select avg(sal) from emp where dno=1;

 

--查询出所有的职位名称去除重复(distinct)

select distinct job from emp;

 

--分组 group by...having...

--查询出每种岗位的平均薪资?

select avg(sal),job from emp group by job;

--查询出每种岗位平均薪水大于8000的岗位名和平均薪水

select avg(sal),job from emp group by job having acg(sal)>8000;

 

--排序 order by ... desc|asc

--查询出员工信息按照月薪从高到低排序

select * from emp order by sal desc;

 

--限定查询结果limit [offset,]rowcount

--查询月薪前三的员工

select * from emp order by sal desc limit 3;

--查询月薪排名第4~6的员工

select * from emp order by sal desc limit 3,3;

  

多表联合查询

--连接查询(等值连接)

--查询出所有员工信息和部门信息

select e.*,d.* from emp e,dept d where e.dno=d.dno;

--内连接:从左表中取出每一条记录,去右表中与所有的记录进行匹配: 匹配必

 

须是某个条件在左表中与右表中相同-最终才会保留结果,否则不保留.

select e.*,d.* from emp e inner join dept d on e.dno=d.dno;

 

--通过对以上结果观察会发现没有员工的部门,以及没有部门的员工都不会显

 

示,如何解决?

--左连接(左外连接):以左表为基准连接右表,左表信息完全显示

select e.*,d.* from emp e left join dept d on e.dno=d.dno;

--右连接(右外连接):以右表为基准连接左表,右表信息完全显示

select e.*,d.* from emp e right join dept d on e.dno=d.dno;

  

子查询

子查询允许把一个查询嵌套在另一个查询当中。子查询,又叫内部查询,相对

 

于内部查询,包含内部查询的就称为外部查询。子查询可以包含普通select可

 

以包括的任何子句,比如:distinct、 group by、order by、limit、join和

 

union等;但是对应的外部查询必须是以下语句之一:select、insert、update

 

、delete、set或 者do。

 

 

 

子查询分为如下几类: 

 

 

1. 标量子查询:返回单一值的标量,最简单的形式。 

 

 

2. 列子查询:返回的结果集是 N 行一列。

 

 

3. 行子查询:返回的结果集是一行 N 列。 

 

4. 表子查询:返回的结果集是 N 行 N 列。  

 

 

 

 

 

 

你可能感兴趣的:(软帝集团培训第四周小结)