橘左京

橘左京 查看完整档案

济南编辑山东理工大学  |  计算机科学与技术 编辑橘左京  |  JAVA开发 编辑 segmentfault.com/u/chen_5f06ec34371fd 编辑
编辑

一位爱好技术的橘右京的某个哥哥橘左京

个人动态

橘左京 赞了文章 · 2月23日

单机最快MQ—Disruptor

单机最快MQ—Disruptor

今天来讲讲我所知道的单机最快的MQ,它叫Disruptor

先来介绍一下Disruptor,从翻译上来看,Disruptor—分裂、瓦解,Disruptor是国外某个金融、股票交易所开发的,2011年获得Duke奖,为成为单机最快的MQ,性能及高,无锁CAS,单机支持高并发

怎么样,心动了没?来来来,让我来带大家学习一下今天的主角—Disruptor

大家可以把Disruptor当做是内存里的高效的队列

Disruptor简介

  • 无锁(CAS)、高并发,使用环形Buffer,直接覆盖(不用清除)旧数据,降低GC频繁,实现了基于事件的生产者消费者模型(观察者模式)

    • 为什么说它是观察者模式呢?因为消费者时刻关注着队列里有没有消息,一旦有新消息产生,消费者线程就会立刻把它消费

环形队列(RingBuffer)

  1. RingBuffer有一个序号sequence,指向下一个可用元素,采用数组实现,没有首尾指针

    • Disruptor要求你对他设置长度的时候,设置成2的n次幂,这样有利于二进制的运算

    image
    首先,它是基于数组实现的,遍历起来要比链表要快
    其次不用维护首尾指针,当然他也没有首尾指针,之需要维护一个sequence即可

  2. **当所有位置都放满了,再放下一个时,就会把0号位置覆盖掉

这时就会有小伙伴着急了,怎么能覆盖掉呢,那我数据不就丢失了吗?**

那肯定是不会就让他这么轻易滴把这数据覆盖掉滴,当需要覆盖数据时,会执行一个策略,Disruptor给提供多种策略,说说比较常用的

  • BlockingWaitStrategy策略,常见且默认的等待策略,当这个队列里满了,不执行覆盖,而是在外面阻塞等待
  • SleepingWaitStrategy策略,看字面意思,用睡眠来等待,等待中循环调用LockSupport.parkNanos(1)来睡眠
  • YieldingWaitStrategy策略,循环等待sequence增加到合适的值,循环中调用Thread.yieId(),允许其他准备好的线程执行

Disruptor开发步骤

  1. 定义Event—队列中需要处理的元素
  2. 定义Event工厂,用于填充队列
  3. 定义EventHandler(消费者),处理容器中的元素
//定义Event消息(事件)类
public class LongEvent{

    private long value;
    private String name;

    @Override
    public String toString() {
        return "LongEvent{" +
                "value=" + value +
                ", name='" + name + '\'' +
                '}';
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public long getValue() {
        return value;
    }
    public void setValue(long value) {
        this.value = value;
    }
}
//定义消息(事件)工厂
public class LongEventFactory implements EventFactory<LongEvent> {
    @Override
    public LongEvent newInstance() {
        return new LongEvent();
    }
}
//定义消息(事件)的消费方式
public class LongEventHandler implements EventHandler<LongEvent> {
    @Override
    public void onEvent(LongEvent longEvent, long l, boolean b) throws Exception {
        System.out.println(longEvent.getName()+"-----"+longEvent.getValue());
    }
}
//消息(事件)生产者
public class LongEventProducer {
    private final RingBuffer<LongEvent> ringBuffer;

    public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }
    public void onData(long val, String name) {
        long sequence = ringBuffer.next();
        try {
            LongEvent event = ringBuffer.get(sequence);
            event.setValue(val);
            event.setName(name);
        } finally {
            ringBuffer.publish(sequence);
        }
    }
}
public static void main(String[] args) {
        //new一个消息(事件)工厂
        LongEventFactory factory = new LongEventFactory();
        //设置环形Buffer的SIZE
        int size = 1024;
        //new Disruptor,参数是消息(事件)工厂,Buffer的Size,线程工厂
        Disruptor<LongEvent> longEventDisruptor = new Disruptor<LongEvent>(factory, size, Executors.defaultThreadFactory());
        //设置如何消费生产者产出的消息(事件)
        longEventDisruptor.handleEventsWith(new LongEventHandler());
        //启动--环形Buffer创建成功,所有的位置均已创建好Event对象
        longEventDisruptor.start();
        //获取Disruptor的环形Buffer
        RingBuffer<LongEvent> ringBuffer = longEventDisruptor.getRingBuffer();
        //new 消息(事件)生产者
        LongEventProducer producer = new LongEventProducer(ringBuffer);
        //循环调用-往里添加消息
        for(long l = 0; l<100; l++) {
            //TODO   调用producer的生产消息(事件)的方法
            producer.onData(l,"MingLog-"+l);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //将消息(事件)发布出去
        longEventDisruptor.shutdown();
    }

回过头来看看,为什么Disruptor这么快呢?

  1. 底层是数组,循环起来要比链表快
  2. 没有首尾指针,免去了维护两个指针的时间
  3. start()方法被调用,Disruptor被初始化,所有可用空间上的Event全部被初始化(提前创建好,每次进来在原对象上进行修改,不用重新new,不用创建新的对象,也就可以降低GC的频率),因为是一开始就把所有的Event初始化好的,所以next获取下一个可用的Event时就不需要再去判断该Event是否被初始化,减少了一步判断
  4. Disruptor的Size是2的n次幂,方便进行二进制位运算,来确定消息应该放在那个可用区域

好了,Disruptor讲解到这里就结束了,大家有什么想要学习的都可以私信或评论告诉我哦\~ 我会尽全力满足大家滴,我学,你也学,咳咳\~广告看多了

点赞、关注来一波好吗,秋梨膏~

查看原文

赞 2 收藏 1 评论 2

橘左京 发布了文章 · 2月22日

针对新手的MYSQL存储过程详解

一位爱好技术的橘右京的哥哥橘左京

在这里插入图片描述

前言:什么是存储过程?存储过程就像是一个接口,可以直接去调用,不需要重复的编写。

1.1 存储过程和函数概述

存储过程和函数是事先经过编译并存储在数据库的一段SQL语句的集合,调用存储过程和函数可以简化开发人员的很多工作,减少数据和应用服务器之间的传输,对于提高数据处理的效率是有好处的。
存储过程和函数的区别在于函数必须有返回值,而存储过程没有。

1.2 创建存储过程

语句:

delimiter $
create procedure 存储过程名称()
begin
SQL语句;
end$

释义:delimiter的中文解释为‘分隔符’,表示将“$”代替“;”设置为分隔符,因为在begin后的SQL语句中需要以";"结尾,所以就要设置一个与";"区分开的分隔符。

1.3 调用存储过程

语法:call 存储过程名称;
执行创建存储过程完成后,使用调用方法调用存储过程。

1.4 查看存储过程

查询数据库中的存储过程

select name from mysql.proc where db = 'test'

查询存储过程的状态信息

show procedure status;

1.5 变量

· DECLARE
通过DECLARE可以定义一个变量,该变量的作用范围用于BEGIN...END之间

1.5.1 声明变量示例:
案例:声明一个年龄变量并查询值

delimiter $
create procedure 存储过程名称()
begin
declare age int default 0;
select  concat('num的值是',age);
end $

1.5.2 SET赋值示例:
案例:声明一个年龄变量并通过SET赋值后查询值

delimiter $
create procedure 存储过程名称()
begin
declare num int default 0;
set num = num + 10;
select  concat('num的值是',num);
end $

1.5.3 select ...into...赋值示例:
案例:声明一个年龄变量并通过SELECT INTO 赋值后查询值

delimiter $
create procedure 存储过程名称()
begin
declare num int;
select count(1) into num from bsx_user;
select num;
end $

1.6 IF语法判断

案例:当年龄段为12岁以下输出青年,当年龄在12-17输出青少年,18-29岁输出青年

delimiter $
create procedure test01()
begin
declare age int default 15;
declare words varchar(20) default 10;
if age <=11 then
set words = '儿童';
elseif age >= 12 and age <= 17 then 
set words = '青少年';
elseif age >=18 and age <= 29 then
set words = '青年';
end if;
select concat('年龄:',age,'属于:',words);
end $

1.7 输入/输出 参数

1.7.1 案例:输入参数 传参
-- 当年龄段为12岁以下输出儿童,当年龄在12-17输出青少年,18-29岁输出青年

语法:create procedure test01([in/out/inout] 参数名 参数类型)
IN: 默认为该方法 调用方传入值作为输入参数
OUT: 该参数作为输出,也就是参数可以作为返回值
OUTIN: 既可以作为输入参数,也可以作为输出参数

创建可传入参数的存储过程:

>delimiter $
create procedure test01(in age int)
begin
declare age int default 15;
declare words varchar(20) default 10;
if age <=11 then
set words = '儿童';
elseif age >= 12 and age <= 17 then 
set words = '青少年';
elseif age >=18 and age <= 29 then
set words = '青年';
end if;
select concat('年龄:',age,'属于:',words);
end $

调用存储过程:

call test01(15)

1.7.2 案例:输出参数 传参
-- 当年龄段为12岁以下返回儿童,当年龄在12-17返回青少年,18-29岁返回青年
根据传入的年龄大小返回对应的年龄区间名称:

delimiter $
create procedure test01(in age int,out words varchar(20))
begin
if age <=11 then
set words = '儿童';
elseif age >= 12 and age <= 17 then 
set words = '青少年';
elseif age >=18 and age <= 29 then
set words = '青年';
end if;
end $

调用存储过程:

call test01(15)

查询返回的结果:

select @words ;         (words是声明的变量名)
小知识:
@words:像这种前面带着@符号的变量称为会话变量,在整个会话过程起作用,类似于全局变量。
@@words:带有两个@@符号的被称为系统变量。

1.8 CASE语法结构

1.8.1 方式一(基本的CASE语法结构)
语法:

case XXX
when 1 then
赋值;
when 2 then
赋值;
else
赋值;
end case;

创建存储过程:
(输入1返回1岁 输入2返回2岁,输入其他文本输出"其他")

delimiter $
create procedure test01(age int,out words varchar(20))
begin 
case age
when 1 then
set words = '一岁';
when 2 then
set words = '二岁';
else  
set words = '其他';
end case;
end $;    

调用存储过程:

call test01(1,@words)

查询返回的结果:

select @words;

1.8.2 方式二(带有表达式的CASE语法结构)
语法:

case
when 表达式 then
赋值;
else
赋值;
end case;

创建存储过程:
(输入0-12 返回儿童,输入13-17返回青少年,输入18-29返回青年,输入其他值返回“老年”)

delimiter $
create procedure test01(age int)
begin 
declare words varchar(20);
case 
when age >=0 and age <= 12 then
set words = '儿童';
when age >=13 and age <= 17 then
set words = '青少年';
when age >=18 and age <= 29 then
set words = '青年';
else  
set words = '老年';
end case;
select words;
end $;

调用存储过程查询返回的结果:

call test01(15);

1.9 While循环

特征:满足条件继续循环
语法:

while a<=10 do
....
end while;

创建存储过程:
(输入一个数,累加超过这个数字时候停止循环并显示数字)

delimiter $
create procedure test01(n int)
begin
declare total int default 0;
declare num int default 1;
while total <= n do
set total = total + num;
set num = num + 1;
end while;
select total;
end $

调用存储过程:

call test01(2)

1.10 repeat循环

特征:满足条件退出循环
语法:

repeat
循环语句...
until 条件语句
end repeat;

创建存储过程:

(计算 1+到n的值)
delimiter $
create procedure test01(n int)
BEGIN
declare num int default 0;
repeat 
set num = num + n;
set n = n-1;
until  n = 0
end repeat;
select num;
end $

调用存储过程:

call test01(5)

1.11 loop循环

特征:满足条件退出循环
语法:

XX:loop (XX代表别名)
循环语句...
if XX<=0 then (因为loop不带有停止循环的判断语句 所以用IF)
leave c;
end if;
end loop c;

创建存储过程:
(计算 1+到n的值)

delimiter $
create procedure test01(n int)
BEGIN
declare num int default 0;
c:loop
    set num = num + n;
    set n = n - 1;
    if n <= 0 then
    leave c;
    end if;
end loop c;
select num;
end $

调用存储过程:

call test01(5)

觉得有帮助可以收藏文章

在这里插入图片描述

查看原文

赞 0 收藏 0 评论 0

橘左京 发布了文章 · 2月7日

初学者都能看懂的MYSQL索引基础


>一位爱好技术的橘右京的哥哥橘左京

image

索引的作用

索引用于快速查找表中数据的值,若不使用索引Mysql就会进行逐行查找,数据量大的情况下效率极低;若使用索引,可快速达到位置进行查找,不会去查找无用数据,效率高。

索引就像书中的目录,可直接通过目录去查找内容所在页数,而不需要一页页的查找。

优势及劣势

优势

1).数据量大的情况下大大加快查询速度,降低数据据IO成本。
2).通过索引对数据进行排序,降低数据排序的成本,降低CPU消耗。

劣势

1).在新增、修改、删除时,索引也需要创建或维护,所耗费的时间也会增加。
2).索引实际上也是一张表,会存放到一个索引文件中,保存了主键和索引字段,并指向实体类的记录,所以索引也占用一定的空间,数据表中的数据会有最大上线设置,如果有大量的索引,可能数据表会更快到达上限值。

使用原则

合理使用索引,对于常用于查询的字段进行设置索引,对于经常更新的表避免使用太多的索引。若数据量较小也不必使用索引,可能不会起到作用。

索引主要分类

1).单值索引:一个索引只能包含一个列,一个表可以有多个单值索引。
2).唯一索引:索引列的值必须唯一,但允许有空值。
3).复合索引:即一个索引包含多个列

索引语法

创建索引
create [UNIQUE|FULLTEXT|SPATIAL] INDEX xd_dog_name [USING index_type] on dog
查看索引:
create index 索引名称 on 表名(字段名称)
删除索引:
show index from 表名
修改表索引:
drop index 索引名称 on 表名
为表中列添加一个主键索引。
alert table 表名 add primary key(字段名)
为表中列添加一个唯一索引(字段值必须唯一,可以有N个null)。
alert table 表名 add unique 索引名称(字段名)
为表中列添加一个普通索引。
alert table 表名 add index 索引名称(字段名称)
为表中列添加一个全文索引。
alert table 表名 add fulltext 索引名称(字段名称)

索引设计原则

1).对查询操作多且数据量大的表建立索引。
2).索引字段的选择最佳候选应当从where语句子条件提取。
3).索引并不是越多越好,尤其增删改操作越多,维护索引的成本就越高。
4).若有过多索引Mysql会出现选择困难症,虽然最后会选择一个有效的索引,但无疑增加了时间消耗。
5).使用唯一索引,区分度越高检索效率越高。
6).使用短索引,索引创建后也是用硬盘存储,可提升索引访问的IO效率,也可提升总体效率。
7).利用最左索引,使用复合索引创建的索引,只要包含创建时的第一个字段就可以使用索引。
如:id name age 搜索id的时候可使用索引、搜索ID Name的时候也可使用索引、搜索ID Name Age的时候也可以使用索引

新的一年新气象,new出对象不重样。
image

查看原文

赞 1 收藏 0 评论 0

橘左京 关注了问题 · 2月5日

解决PageHelper分页 空指针异常

开发环境

springColud、springBoot、myBatis、sqlServer、PageHelper

问题描述

  1. 旧程序添加了一个新的分页查询列表
  2. 需求很简单,但是代码完成执行查询一直报错,提示Error querying database. Cause: java.lang.NullPointerException
  3. xml中的sql语句在数据库多次测试缺失无误
  4. 经过测试后发现,如果不启动PageHelper分页就可以正常执行
  5. 启动分页直接报错

具体错误提示

图片.png

关注 2 回答 3

橘左京 回答了问题 · 2月5日

解决PageHelper分页 空指针异常

建议尝试将mapper中的 association中的colum为‘experience’image.png

关注 2 回答 3

橘左京 发布了文章 · 2月5日

如何对网站排名进行优化?带你深入理解SEO

橘右京的某个哥哥橘左京

1.SEO介绍

SEO(Search Engine Optimization):汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜素引擎内的自然排名。目的是让其在行业内站在领先地位,获取品牌效益。很大程度上是网站经营者的一种商业行为,将自己或公司排名前移。

2.百度搜索排名流程

1).放出蜘蛛(百度爬虫)
2).蜘蛛来抓取数据
3).页面的收录
4).算法计算得分
5).排名

3.搜素引擎爬虫

搜索引擎会模仿普通用户,抓取网站有效信息,若网站需要登录才可访问蜘蛛很难收录除非这种网站流量较多。蜘蛛会有两步操作,来访和返回,来访是蜘蛛到网站上进行数据爬取,爬取完成后会将页面数据返回百度,百度会对页面进行计算,若页面质量不合格,蜘蛛对网站的爬行次数就会减少。

4.网络爬虫的管理规则

1.每个网址链接都是蜘蛛的入口,当链接长度越长时,蜘蛛访问越慢,会导致爬行次数减少。
2.域名尽量选择英文命名方式。
3.提升网站访问速度,若访问较慢,则收录概率较低。
4.识别难度的问题,像图片、视频识别难度较高,一般不会识别。之所以bilibili视频网站的排名这么高,除了优化问题还有就是因为流量大。
5.有效收录,有价值的信息。
6.一个页面有15个链接以上更容易被收录。
7.访问日志,访客访问网站服务器会生成一个文档记录当天数据值。若蜘蛛访问次数少说明质量较差。
网络爬虫的管理规则

根目录:wwwlogs->压缩包解压->.log改为txt->用Excel打开

5.如何提升网站的收录数量

百度放出蜘蛛,蜘蛛来到页面获取数据之后会返回到百度,经过一系列计算得到页面是否有价值,若是无价值内容,对百度就是一种差评所以收录几率极小,若页面有价值,百度就会收藏起来,只有收藏后才能获得排名的资格,收录数量越多排名机会越大,但是百度有一个收录质量评级,分为有效收录和无效收录,如是无效收录,百度会给予惩罚,如降权。

页面可直接提交百度收录就行收录操作。

6.网站权重

百度站长平台正式发出公告:百度 pagerank、百度权值是不存在的。但到底是否存在需要进一步求证。若想增加权重,最简单粗暴的方式就是增加网站在搜索引擎的日点击量。

7.高级SEO核心数据计算

1.展现量:假设网站排名在第九名,滑倒最下面看到本网站,就算一次展现量。
2.点击量:用户在搜索引擎点击本网站
3.点击率:点击次数/展现量
4.访问量:一天有多少用户访问过本网站
5.跳出率:进入本网站后接着关闭
6.停留时间:用户在本网站的停留时间

8.关键词选择的四大技巧

1.指数(百度指数): 使用百度人群的搜索习惯 选择关键词500-600指数之间
2.相关结果:选择1000万左右相关结果的关键字
3.商业价值
4.首页及标题关键词数量(Title)

9.TDK

TDK是SEO界的三大标签,排名若存在打分100分,好的TDK占40%

T:标题 影响网站在行业网站排名的重要因素之一
D:网站描述 根据用户需求书写,决定用户是否想要点击的欲望
K:关键字

标题书写规格:

关键词1-关键词2-关键词3-品牌词

表述书写规格

60-80字 超出80会以省略号显示,抓住用户需求(1.用户的痛点 2.行业的优势 3.包含关键字)

举例:

山东信息科技有限公司具有12年电器系统行业研发经验,专注打造高质量空压机品牌。主营:空气压缩机、高压空压机、无油空压机等设备研发,安全,耐用保修。

10.高阶栏目打造

栏目的作用是引导用户点击,即足够吸引人,抓住用户的需求。将栏目根据用户需求从重要到不重要依次排开,以用户需求划分,不得超过九个。

如:网站在搜索引擎中是以得分来排名的,当网站存在一定用户后访问栏目,即可带动其他栏目的访问。如果栏目过多,总分一百分十个栏目得分平均分只能十分,如果有五个栏目,每个栏目可得二十分,再将这二十分依次划分到文章,就影响到了文章页面的排名,栏目越少,文章栏目排名就能够越靠前。可通过百度搜素的推荐进行栏目的设定。
高阶栏目打造
高阶栏目打造

11.利用锚文本提升网站收录

锚文本的作用:

1)达到站内站外跳转的目的。一个网站的点击率越高说明网站质量越高,越容易获得排名。
2)增加用户停留时间,跳转到新的链接既有了访问量又有了停留时间。
3)增加蜘蛛的爬行。蜘蛛在爬取网站的时候遇到超链接会跳转进去接着爬,蜘蛛存准率较高。

高质量锚文本要求:

①链接文字与跳转页面内容相符
②链接文字最好使用排名关键字(TDK中包含的文字)
③锚文本设置密度不应过多(不超过1%)
④不应多个锚文本跳转同一个链接(会造成回链)
⑤站在用户需求,若有大量锚文本并且不被点击可能会导致收录排名较差。

12.网站文章书写的技巧

1)百度鼓励原创,但更追求用户体验,初期网站建议使用伪原创(修修改改)
2)图文结合,建议配三张图片,增加用户停留时间。
3)字数要求,不低于800字,若未达到八百字百度基本不会认可文章内容。
4)不可乱写,会影响有效收录 。(有效收录:点击率、停留时间长)
5)挖掘关键词,使用长尾关键词。

13.高级SEO外链算法

外链作用:将链接放至其他网站,我们网站就从他人网站上获得了用户,从而百度计算我们文章排名的几率大大增加。可以吸引蜘蛛。

2012年百度推出绿萝算法,专门打击无效,低质外链。

若做外链就要选择外链平台,放置我们的锚文本链接,对链接进行文字描述引导用户点击(最全的免费电影网站:www.*.),切记不可描述与链接不符造成影响网站整体排名,不可将同样的文字描述发到不同网站,百度绿萝算法会进行检测,对网站排名起到反作用。
高级SEO外链算法

14.通过友情链接提升排名

友情链接即为链接互换,挂上对方的网站链接像交朋友一样。作用是可带动网站之间的互动性。若是新站,百度蜘蛛很少会爬取网站,就可通过交换友链来达到优化新网站的目的。

友情链接交换规则:

1)友情链接交换至30个左右,过少会发挥不了价值,过多会导致蜘蛛分散。
2)选择周边行业或同行业
3)尽量选择高权重站点交换
4)新站交换链接可选择一些高质量站点

15.闪电算法-秒排的数据要求

百度针对网站加载速度优化规则:

①小于2S(加分项)
②2S-3S(不扣不加)
③大于3S(扣分)

影响网站加载速度的相关因素:

①选择错误模板
②代码优化问题
③过多的CSS
④拖累加载(超多图片、视频多媒体文件)
⑤服务器性能

16.网站SEO域名选择方式

网站优化实际在建站的时候就已经开始布局,域名直接决定了用户对网站的记忆属性,它分为三部分,前缀、主体、后缀,最重要的就是主体部分,可选择全拼及缩写,代表公司或产品的域名。

如:www.bilibili.* 在百度搜bilibili B站的域名也会被标红,有助于对网站的排名。

网站SEO域名选择方式

17.H标签的细节优化

H标签是HTML的一种代码格式,百度蜘蛛抓取一篇文章会有一个重点,就是H标签,蜘蛛会认为这是等级最高的一种代码标签,优先获取里面的内容(<h1>*</h1>),<h1>一般只有一个,将文章命名为符合实际内容含有关键字的标题。

18.nofollow的实用技巧

nofollow的作用是告诉蜘蛛不要来爬取链接或对链接分配权重或分数。

写法:< a target='blank_' rel='nowfollow' herf='/index.html'>AAAA< /a >

应用范围:

1)外部链接

①别人到你网站删挂外链要给他加nowfollow,否则会蜘蛛跑到别人网站。
②若网站存在QQ客服聊天,QQ客服链接也要挂上nowfollow
③广告也要挂上nowfollow

2)不需要的页面

①关于我们
②联系我们
(因为这两种页面不需要排名,可适当根据自己的需求进行调整)

19.网站ALT代码优化

alt代码的作用是给图片加以说明,因为蜘蛛抓取数据的时候识别图片难度会很高,若蜘蛛很难判断网站的内容可能会不收录或降低排名,这时ALT的作用就凸显出来了,有alt和无alt得分差别会很大。

例:若文章内容是夏季绿萝的养护方法,配图是一张绿萝,我们就可以给图片命名为绿萝的养护方法或更细腻的一种描述

网站ALT代码优化

20.企业网站的优化

做网站要追求到一个点叫做人无我有,人有我优,前期站点是没有流量的只能依靠蜘蛛去做优化,后期站点可通过流量,因为有原始用户的积累。

企业站点分为两类:

①专门提供产品服务的站点

若是多种类型产品,栏目决定了网站优化方向,除了首页外首先应该划分产品类别,将产品类别再详细划分为热门产品,其他栏目可划分产品价格、维修保障、公司保障、产品案例,抓住用户的需求去划分类别。

企业网站的优化

②线上提供某种服务需求的站点

例如装修、搬家、开锁等站点,可划分服务分类、服务流程、服务区域、服务价格等。

企业网站的优化

总结:
网站SEO是一个漫长的过程,万不可急于求成,建议先学习SEO知识后建站,以免对网站收录及排名造成不好的影响。

网站不可盲目的修改TDK,经过实验,若盲目修改TDK百度算法检测到网站过于优化,很有可能会被K站,这是一个循序渐进的过程。丰富网站内容,以高质量文章及良好的页面排版和更关键的TDK来一步步完成我们的SEO之路。

1).优化网站TDK
2).优化栏目
3).增加内容(锚文本)
4).增加 多媒体文件 alt标签(alt标签 图片及视频描述)
5).吸引流量
6).增加相应nofollow标签
7).H 标签优化
8).丰富主营业务、应用功能、应用案例内容
9).完善其他栏目的响应内容
10).更新快照
11).外链
12).保证服务器稳定,减少访问响应时间
13).增加网站高质量文章

        ————部分内容翻译于燃灯教育视频
看完一键三连,就能迎娶柳岩

image

查看原文

赞 1 收藏 0 评论 3

橘左京 赞了文章 · 2月5日

多线程高并发学习之并发容器

多线程高并发学习之并发容器

HashMap相关的同步容器

  • 前世今生介绍:HashMap是从HashTable演变过来的,HashTable设计之初的意愿是容器的的所有方法必须都得是同步的,所以HashTable的所有方法都是加了synchronized关键字来保证同步,这显然是不太合理的,因为大多数情况下,都是只有一个线程来操作容器,所以又在HashTable之后推出了HashMap

    • HashTable——>全锁操作
    • HashMap——>无锁操作
    • ConcurrentHashMap——>新的同步容器(CAS)
    • HashMap也应该有同步方法,所以又出了一个Collections这么一个工具类,他可以把HashMap变成一个同步容器,如下图,还可以将许多容器都变为同步容器
    • image
    • Collections.synchronizedMap( )给出的同步容器HashMapHashTable有什么区别呢,区别其实很小,就是HashTable用的是方法锁,而Collections.synchronizedMap( )用的是同步代码块,都是用的synchronized,只不过相比于HashTable锁的力度要小一些,效率略高一丢丢ConcurrentHashMap采用的是CAS无锁操作,在put的过程中如果没有发生冲突,则采用CAS操作进行无锁化更新只有发生了哈希冲突的时候才锁住在链表上添加新Node或者更新Node的操作
  • 读写效率:

    • HashTable写入效率高,实测100W数据写入用时700毫秒左右,读效率低,100W数据读取用时37秒左右
    • Collections.synchronizedMap( )写入效率高,实测100W数据写入用时600毫秒左右,读效率低,100W数据读取用时38秒左右
    • ConcurrentHashMap写入效率低,实测100W数据写入用时1.8秒左右,读效率超高,100W数据读取用时1.7秒左右
    • 总结:实际用哪一个需要看项目的使用场景,到底是读操作多,还是写操作多,然后根据实际压测数据来决定到底是用哪个同步容器

List、Vector、Queue

  • List同步需要加锁,或者上图所示,使用collectios的synchronizedXXX的方法,获取同步的List,原理也是synchronized代码块
  • Vector是同步容器,是在方法上加了synchronized关键字,为方法锁,相比synchronizedList锁的力度要大一些,所以效率偏慢一丢丢
  • Queue队列,实现类中有多个同步队列,都可以实现同步,甚至还有的实现了生产者消费者模型,所以大并发下单个元素的操作,尽量可以多考虑Queue,少考虑List

经常在多线程下使用的容器

Map

  • ConcurrentHashMap,基于CAS实现,不多解释
  • ConcurrentSkipListMap,基于跳表实现

    • 可能是因为,考虑到利用CAS实现了一个ConcurrentHashMap,也应该需要用CAS实现一个 ”ConcurrentTreeMap“ (此处多逼逼一句,TreeMap基于红黑树实现),但不幸的是,使用CAS实现 ”ConcurrentTreeMap“ 太难了,难度超高,超复杂,所以退一步,使用跳表实现了一个ConcurrentSkipListMap
    • image
  • HashTable
  • Collections.synchronizedMap( )

List

  • CopyOnWriteArrayList,写时复制,顾名思义,在写入数据的时候,将array数组copy一次,如下图

    • image
    • 有点类似Lock里的ReadWriteLock,读不加锁,写入加锁
  • Collections.synchronizedList( )

    • 和上边提到的Collections.synchronizedMap( )一个样子,都是同步代码块

Queue

  • ConcurrentLinkedQueue

    • 方法介绍:

      • add:添加元素,加不进去,满了,跑异常
      • offer:添加元素,添加成功返回true,满了添加不进去了,返回false
      • peek:获取元素,但是获取后不删除元素
      • poll:获取元素并且删除元素

BlockingQueue:天生的生产者消费者模型

LinkedBlockingQueue无界队列

  • 介绍:基于链表实现的无界队列,可以一直添加,直到内存溢出
  • 方法介绍:除了上边的add、offer、peek、poll方法外

    • put:添加元素,如果添加满了,就阻塞住,等待可以继续添加元素
    • take:获取元素,如果没有可以获取的元素,就阻塞住,等待可以继续往外取元素

ArrayBlockingQueue有界队列

  • 与LinkedBlockingQueue相同,只不过是指定大小的,有界的

PriorityQueue

  • 介绍:可以根据添加进来的对象进行比较排序,然后安顺序取出

    • 例如:依次添加“a”、“z”、“f”、“c”,然后循环调用poll,依次取出,顺序是排好序的

DelayQueue时间排序队列

  • 介绍:根据时间排序,要进入队列的对象必须实现Delayed接口,重写getDelay(获取等待时间)方法以及compareTo(比较时间)方法
  • image

SynchronusQueue

  • 介绍:容量为0的队列,其实,这东西不是用来装东西的,是用来让一个线程给另外一个线程下达任务的,一个线程往里放数据,等待另一个线程来取数据
  • 容量为0,所以调用add方法往里面添加数据是会报错,正确的使用方法是一个线程调用put方法往里放数据,另一个线程调用take方法,取数据
  • image
  • image

TransferQueue

  • 介绍:具有独有的transfer方法,调用该方法写入数据,在被其他线程取走数据前一直阻塞的等着,知道有人将数据取走
  • 方法:

    • transfer方法,写入数据,并且阻塞住,等待数据被取走后继续执行
说了这么多,那么,你学废了吗?
不点个赞再走嘛

image

查看原文

赞 3 收藏 1 评论 2

橘左京 关注了专栏 · 2月5日

思否编程 技术分享

思否编程技术内容分享

关注 8838

橘左京 关注了标签 · 2月5日

程序员

一种近几十年来出现的新物种,是工业革命的产物。英文(Programmer Monkey)是一种非常特殊的、可以从事程序开发、维护的动物。一般分为程序设计猿和程序编码猿,但两者的界限并不非常清楚,都可以进行开发、维护工作,特别是在中国,而且最重要的一点,二者都是一种非常悲剧的存在。

国外的程序员节

国外的程序员节,(英语:Programmer Day,俄语:День программи́ста)是一个俄罗斯官方节日,日期是每年的第 256(0x100) 天,也就是平年的 9 月 13 日和闰年的 9 月 12 日,选择 256 是因为它是 2 的 8 次方,比 365 少的 2 的最大幂。

1024程序员节,中国程序员节

1024是2的十次方,二进制计数的基本计量单位之一。程序员(英文Programmer)是从事程序开发、维护的专业人员。程序员就像是一个个1024,以最低调、踏实、核心的功能模块搭建起这个科技世界。1GB=1024M,而1GB与1级谐音,也有一级棒的意思。

从2012年,SegmentFault 创办开始我们就从网络上引导社区的开发者,发展成中国程序员的节日 :) 计划以后每年10月24日定义为程序员节。以一个节日的形式,向通过Coding 改变世界,也以实际行动在浮躁的世界里,固执地坚持自己对于知识、技术和创新追求的程序员们表示致敬。并于之后的最为临近的周末为程序员们举行了一个盛大的狂欢派对。

2015的10月24日,我们SegmentFault 也在5个城市同时举办黑客马拉松这个特殊的形式,聚集开发者开一个编程大爬梯。

特别推荐:

【SF 黑客马拉松】:http://segmentfault.com/hacka...
【1024程序员闯关秀】小游戏,欢迎来挑战 http://segmentfault.com/game/

  • SF 开发者交流群:206236214
  • 黑客马拉松交流群:280915731
  • 开源硬件交流群:372308136
  • Android 开发者交流群:207895295
  • iOS 开发者交流群:372279630
  • 前端开发者群:174851511

欢迎开发者加入~

交流群信息


程序员相关问题集锦:

  1. 《程序员如何选择自己的第二语言》
  2. 《如何成为一名专业的程序员?》
  3. 《如何用各种编程语言书写hello world》
  4. 《程序员们最常说的谎话是什么?》
  5. 《怎么加入一个开源项目?》
  6. 《是要精于单挑,还是要善于合作?》
  7. 《来秀一下你屎一般的代码...》
  8. 《如何区分 IT 青年的“普通/文艺/二逼”属性?》
  9. 程序员必读书籍有哪些?
  10. 你经常访问的技术社区或者技术博客(IT类)有哪些?
  11. 如何一行代码弄崩你的程序?我先来一发
  12. 编程基础指的是什么?
  13. 后端零起步:学哪一种比较好?
  14. 大家都用什么键盘写代码的?

爱因斯坦

程序猿崛起

关注 155341

橘左京 关注了标签 · 2月5日

docker

an open source project to pack, ship and run any application as a lightweight container ! By Lock !

关注 44408

认证与成就

  • 获得 4 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-07-09
个人主页被 705 人浏览