极客996

极客996

  • 28文章
  • 1评论
  • 6959文章浏览

对象锁如何理解?

/**
 * 对象锁: 多个线程访问同一个实例对象会对该实例对象的锁进行竞争,谁先拿到谁就能操作上锁的资源
 * 
 * 以下是三种对象锁的设置方式
 */

public class ObjectLock {
    private Object lock = new Object();

    /**
     * 1.锁住非静态变量
     *
     * @throws InterruptedException
     */
    public void lockObjectField() throws InterruptedException {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(2 * 1000);
        }
    }

    /**
     * 2.锁住 this 对象 this 就是当前对象实例
     *
     * @throws InterruptedException
     */
    public void lockThis() throws InterruptedException {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(2 * 1000);
        }
    }

    /**
     * 3.直接锁住非静态方法
     *
     * @throws InterruptedException
     */
    public synchronized void methodLock() throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Thread.sleep(2 * 1000);
    }

    public static void main(String[] args) {
        //创建线程共享的资源
        ObjectLock objectLock = new ObjectLock();
        for (int i = 0; i < 5; i++) {
            //创建多线程访问同一个对象
            Thread worker = new Thread(new ObjectLockWorker(objectLock));
            worker.setName("geek996-" + i);
            worker.start();
        }
    }

    public static class ObjectLockWorker implements Runnable {
        ObjectLock objectLock;
        public ObjectLockWorker(ObjectLock objectLock) {
            this.objectLock = objectLock;
        }

        @Override
        public void run() {
            //访问锁资源
            try {
                // 方式 1
                objectLock.lockObjectField();
                //方式 2
                objectLock.lockThis();
                // 方式 3
//                objectLock.methodLock();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Rick  173  2020-10-12 阅读全文

Mysql——使用ngram解析器创建全文索引模拟搜索引擎查询

开始之前,先说一下全文索引的版本、存储引擎、数据类型的支持情况 MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引; MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引; 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。 为什么要使用ngram解析器? 内置的MySQL全文解析器使用单词之间的空格作为分隔符来确定单词的开始和结束位置,这在处理不使用单词分隔符的表意文字语言时是一个限制。为了解决这个限制,MySQL提供了一个ngram全文解析器,它支持中文、日文和韩文(CJK)。InnoDB和MyISAM支持ngram全文解析器。 索引需要了解的参数 # 参数名称 默认值 最小值 最大值 作用 1 ft_min_word_len 4 1 3600 MyISAM 引擎表全文索引包含的最小词长度 2 ft_query_expansion_limit 20 0 1000 MyISAM引擎表使用 with query expansion 进行全文搜索的最大匹配数 3 innodb_ft_min_token_size 3 0 16 InnoDB 引擎表全文索引包含的最小词长度 4 innodb_ft_max_token_size 84 10 84 InnoDB 引擎表全文索引包含的最大词长度 5 ngram_token_size 2 1 10 使用ngram解析器创建的索引时,以上四种参数不生效。如果你想通过单个词匹配,将该值设置为1 6 INNODB_FT_DEFAULT_STOPWORD 在InnoDB表上创建FULLTEXT索引所使用的默认停止字表。通俗点就是用里面的词进行索引查询直接返回空 如何理解ngram_token_sizez这个参数? 例词 '信息系统' 在设置为不同值时的分词情况     ngram_token_size=1 : '信', '息', '系', '统'     ngram_token_size=2 : '信息', '息系', '系统';     ngram_token_size=3 : '信息系', '息系统';     ngram_token_size=4 : '信息系统'; 创建方式全文索引方式 ALTER TABLE user_message ADD FULLTEXT INDEX msg_content_idx (content); //常规创建
ALTER TABLE user_message ADD FULLTEXT INDEX msg_content_idx (content) with PARSER ngram; //ngram创建 使用全文索引查询(非ngram解析器同样适用,不过结果不同,达不到我们想要的效果-例如搜索引擎) select * from user_message where MATCH(content) AGAINST('+服' IN BOOLEAN MODE) //通配符搜索模式

select * from user_message where MATCH(content) AGAINST('服* 生日' IN NATURAL LANGUAGE MODE ) //自然语言搜索模式
 对比下效果,为了方便测试索引参数均设置为1 常规分析器 select * from user_message where MATCH(content) AGAINST('今天你生日' IN NATURAL LANGUAGE MODE) //无法匹配数据
 select * from user_message where MATCH(content) AGAINST('今天你生日啊' IN NATURAL LANGUAGE MODE) //常规解析器支持全文匹配 select * from user_message where MATCH(content) AGAINST('[email protected]' IN NATURAL LANGUAGE MODE)  //支持非中文自然语言匹配/通配符匹配 ngram分析器 select * from user_message where MATCH(content) AGAINST('生日' IN NATURAL LANGUAGE MODE)
select * from user_message where MATCH(content) AGAINST('日生' IN NATURAL LANGUAGE MODE) 以上查询结果一样 部分测试代码 ALTER TABLE user_message ADD FULLTEXT INDEX msg_content_idx (content)  ;


select  * from user_message where content like '生日';

select * from user_message where MATCH(content) AGAINST('dd fff geek996' IN NATURAL LANGUAGE MODE)
select * from user_message where MATCH(content) AGAINST('日 生 别' IN NATURAL LANGUAGE MODE)

drop index msg_content_idx on user_message ; 

SELECT * FROM information_schema.`INNODB_FT_INDEX_TABLE`; 总结:了解ngram之后不经意看到ElsaticSearch ,技术互通性还是挺大的。

Rick  162  2020-10-11 阅读全文

Java设计模式——抽象工厂模式

抽象工厂模式应该如何理解原理? 根据我的理解可以分为已下几个关注点: 1.抽象工厂—定义生产的抽象产品,一般为一个产品族 2.具体工厂—实现抽象工厂,一般用于获取每个类型的产品 3.抽象产品—抽象产品类型并集为一个产品族 4.具体产品—抽象产品的具体实现 使用场景:某家服饰公司要生产鞋、衣服、裤子等服装,服装又分婴儿、儿童、成人,请问应该如何设计? 下面是我的设计思路,

Rick  127  2020-10-11 阅读全文

简单谈谈对volatile理解

1.保障线程对主存中该数据的可见性 当修改了增加volatile 的变量时,会马上将变量值写回到主内存中,这时会在store 前对主内存的这个变量加锁,在store 通过总线的时候触发MESI缓存一致性协议,通过总线嗅探器将其他cpu工作内存中缓存该变量的行设置为无效。当cpu 完成变量的write 操作时,再对变量进行解锁。 2.不保证原子性 当线程A对工作内存中的i进行自增的时候,i+1 从主存中读取i i+1 写入主存 当执行第2的时候,变量i并未回到主存中,所以变量未加锁,这时线程B拿到i也进行自增,问题就在这,线程A中变量i的操作还未全部完成,线程B就已经拿到i了,这就违背了原子性的定义——要么成功,要么失败。所以为什么要使用 3.保证有序性 拿单例模式——懒汉式举例,为什么单例对象要加volatile class Singleton {
    //懒汉式
    private volatile static Singleton singleton;

    public static Singleton getInstance(String i) {

        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

} Object obj=new Object(); memory=allocate() //分配内存空间 obj(memory) //初始化对象 obj=memory //设置obj指向分配的内存地址,此时obj不为bull 一个理想中对象的实例化顺序是以上3步,但是编译器在优化的时候可能会打乱顺序,应该不会影响最终结果——实例化。 问题就在实例化的过程中,顺序打算为1-3-2,当另一个线程在执行到3也就是还未初始化对象的时候拿这个对象的实例进行操作就会出现问题。

Rick  102  2020-09-26 阅读全文

Java设计模式——装饰器模式

装饰者模式应该如何理解原理? 根据我的理解可以分为已下几个关注点: 1.被装饰的抽象对象—最终装饰成什么样的一个组合体 2.被装饰对象的实现—以该抽象实例为基础与其他装饰对象为一体 3.抽象装饰器—构造参数必须传入装饰对象,所有的装饰类基础该抽象装饰器 4.装饰器对象的实现—装饰对象为被装饰对象增强功能 /被装饰抽象对象:饮料
interface Drink {
    //价格
    public Integer price();

    //名称
    public String name();

    //描述
    public String desc();
}

//被装饰对象实现:咖啡
class Coffer implements Drink {
    private Integer price = 10;
    private String name = "普通咖啡";

    @Override
    public Integer price() {
        return price;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public String desc() {
        return String.format("[%s] 价格:%d", name(), price());
    }


}

//抽象装饰器
abstract class Decoeator implements Drink {
    protected Drink drink;

    public Decoeator(Drink drink) {
        this.drink = drink;
    }

}

//牛奶装饰器
class MilkDecoeator extends Decoeator {
    private Integer price = 5;
    private String name = "牛奶";

    public MilkDecoeator(Drink drink) {
        super(drink);
    }

    @Override
    public Integer price() {
        return super.drink.price() + price;
    }

    @Override
    public String name() {
        return super.drink.name() + " + " + name;
    }

    @Override
    public String desc() {
        return String.format("[%s]  价格:%d", name(), price());
    }
}

class Sugar extends Decoeator {
    private Integer price = 1;
    private String name = "糖";

    public Sugar(Drink drink) {
        super(drink);
    }

    @Override
    public Integer price() {
        return super.drink.price() + price;
    }

    @Override
    public String name() {
        return super.drink.name() + " + " + name;
    }

    @Override
    public String desc() {
        return String.format("[%s]  价格:%d", name(), price());
    }
}

class Banana extends Decoeator {
    private Integer price = 3;
    private String name = "香蕉";

    public Banana(Drink drink) {
        super(drink);
    }

    @Override
    public Integer price() {
        return super.drink.price() + price;
    }

    @Override
    public String name() {
        return super.drink.name() + " + " + name;
    }

    @Override
    public String desc() {
        return String.format("[%s]  价格:%d", name(), price());
    }
} 测试:   public static void main(String[] args) {
        Drink drink = new Coffer();
        System.out.println(drink.desc());
        drink = new MilkDecoeator(drink);
        System.out.println(drink.desc());
        drink = new Sugar(drink);
        System.out.println(drink.desc());
        drink = new Banana(drink);
        System.out.println(drink.desc());
    } 难点:为什么 价格!=上个对象+装饰对象的价格 我们可以理解为最终装饰对象=被装饰对象+所有装饰对象的组合

Rick  114  2020-09-26 阅读全文

Java设计模式——静态代理模式

//静态代理设计实现
interface UserService {
    public void update();
}

class UserImpl implements UserService {
    @Override
    public void update() {
        System.out.println("修改用户..");
    }
}

class UserProxy implements UserService {
    UserService userService;

    public UserProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void update() {
        //操作之前拓展逻辑
        userService.update();
        //操作之后拓展逻辑
    }
}                                    运行: public static void main(String[] args) {                  
    UserProxy proxy = new UserProxy(new UserImpl());      
    proxy.update();                                       
}                                                         缺点:需要为每个代理类实现接口

Rick  108  2020-09-26 阅读全文