tonglin0325的个人主页

Java关键字

private default protected public的访问控制权限

 

protected范例

transient关键字

当使用Serializable接口实现序列化操作时,如果一个对象中的某一属性不希望被序列化,则可以使用transient关键字进行声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

class Person_3 implements Serializable{ //此类的对象可以被序列化
private transient String name;
private int age;

public Person_3(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "姓名:" + name + ", 年龄:" + age;
}


}

public class Serializable_demo {

public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根
// File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
// ObjectOutputStream oos = null;
// OutputStream out = new FileOutputStream(f); //文件输出流
// oos = new ObjectOutputStream(out); //为对象输出流实例化
// oos.writeObject(new Person_3("张三", 30));
// oos.close();

File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f); //文件输入流
ois = new ObjectInputStream(input); //为对象输入流实例化
Object obj = ois.readObject(); //读取对象
ois.close();
System.out.println(obj);
}

}

 

<3>序列化一组对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

class Person_3 implements Serializable{ //此类的对象可以被序列化
// private transient String name;
private String name;
private int age;

public Person_3(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "姓名:" + name + ", 年龄:" + age;
}


}

public class Serializable_demo {

public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根
// File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
// ObjectOutputStream oos = null;
// OutputStream out = new FileOutputStream(f); //文件输出流
// oos = new ObjectOutputStream(out); //为对象输出流实例化
// oos.writeObject(new Person_3("张三", 30));
// oos.close();

// File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
// ObjectInputStream ois = null;
// InputStream input = new FileInputStream(f); //文件输入流
// ois = new ObjectInputStream(input); //为对象输入流实例化
// Object obj = ois.readObject(); //读取对象
// ois.close();
// System.out.println(obj);

Person_3 per[] = {new Person_3("张三",30),new Person_3("李四",31),new Person_3("王五",32)};//定义对象数组
ser(per); //序列化对象数组
Object o[] = dser();
for(int i=0;i<o.length;i++){
Person_3 p = (Person_3) o[i];
System.out.println(p);
}
}

public static void ser(Object obj[]) throws Exception{
File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
ObjectOutputStream oos = null;
OutputStream out = new FileOutputStream(f); //文件输出流
oos = new ObjectOutputStream(out); //为对象输出流实例化
oos.writeObject(obj);
oos.close();
}

public static Object[] dser() throws Exception{
File f = new File("/home/common/software/coding/HelloWord/HelloWord/test.txt");//路径
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f); //文件输入流
ois = new ObjectInputStream(input); //为对象输入流实例化
Object obj[] = (Object[])ois.readObject(); //读取对象数组
ois.close();
return obj;
}

}

volatile关键字

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

    全文 >>

SpringBoot学习笔记——校验

JSR-303提供了一些注解,将其放到属性上,可以限制这些属性的值。

参考:Spring MVC学习笔记——JSR303介绍及最佳实践

校验放在DTO层上,不要和数据库交互的model层混用

关于model,VO等的区别,参考:Spring MVC学习笔记——POJO和DispatcherServlet

如何赋值,参考:优雅的使用BeanUtils对List集合的操作

DTO和DO的转换,可以使用BeanUtils,参考:设计之道-controller层的设计

也可以使用ModelMapper,参考:Spring Boot DTO示例:实体到DTO的转换

如果使用的springboot版本大于2.3.x,需要额外引用依赖

1
2
3
4
5
6
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.1.Final</version>
</dependency>

参考:使用SpringBoot进行优雅的数据验证

全文 >>

Java多线程

Java进程与线程

进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到最终消亡的过程。

多进程操作系统能同时运行多个进程(程序),由于CPU具备分时机制,所以每个进程都能循环获得自己的CPU时间片。

多线程是指一个进程在执行过程中可以产生多个线程,这些线程可以同时存在、同时运行,一个进程可能包含了多个同时执行的线程

比如JVM就是一个操作系统,每当使用java命令执行一个类时,实际上都会启动一个jvm,每一个JVM实际上就是在操作系统中启动一个进程,java本身具备了垃圾回收机制,所以每个java运行时至少会启动两个线程一个main线程另外一个是垃圾回收机制

Java中线程的实现

在Java中要想实现多线程代码有两种手段,一种是继承Thread类另一种就是实现Runnable接口

1.继承Thread类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyThread extends Thread{
private String name;

public MyThread(String name) { //构造方法
super();
this.name = name;
}

public void run(){ //覆写Thread类中的run()方法
for (int i=0;i<10;i++){
System.out.println(name+"运行,i="+i);
}
}

}

public class Thread_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThread mt1 = new MyThread("线程A ");
MyThread mt2 = new MyThread("线程B ");
mt1.start();
mt2.start();
}

}

输出的结果可能是A线程和B线程交替进行,哪一个线程对象抢到了CPU资源,哪个线程就可以运行,在线程启动时虽然调用的是start()方法,但是实际上调用的却是run()方法的主体

如果一个类通过Thread类来实现,那么只能调用一次start()方法,如果调用多次,则将会抛出”IllegalThreadStateException”异常。

 

2.实现Runnable接口

仍然要依靠Thread类完成启动,在Thread类中提供了public Thread(Runnable target)和public Thread(Runnable target,String name)两个构造方法。

这两个构造方法都可以接受Runnable的子类实例对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class MyThread_1 implements Runnable{
private String name;

public MyThread_1(String name) { //构造方法
super();
this.name = name;
}

@Override
public void run() { //覆写Thread类中的run()方法
// TODO 自动生成的方法存根
for (int i=0;i<10;i++){
System.out.println(name+"运行,i="+i);
}
}

}

public class Runnable_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThread_1 mt1 = new MyThread_1("线程A "); //实例化Runnable子类对象
MyThread_1 mt2 = new MyThread_1("线程B "); //实例化Runnable子类对象
Thread t1 = new Thread(mt1); //实例化Thread类对象
Thread t2 = new Thread(mt2); //实例化Thread类对象
t1.start(); //启动线程
t2.start(); //启动线程
}

}

 

通过Thread和Runnable接口都可以实现多线程,其中Thread类也是Runnable接口的子类,但在Thread类中并没有完全地实现Runnable接口中的run()方法。

全文 >>

ubuntu删除输入法后,循环登陆

在登陆界面ctrl+alt+F1进入tty界面,登陆账号,然后输入

1
2
dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P

 

主要就是 sudo chown root:root .Xauthority

应该改成 sudo chown 图形界面的own:图形界面的grp .Xauthority

 

登陆之后没有中文输入法

首先安装fcitx

sudo apt-get install fcitx libssh2-1到搜狗输入法的首页下载deb的安装文件

然后安装搜狗输入法,双击安装或者sudo dpkg -i XXXX.deb

全文 >>

ElasticSearch学习笔记——Request请求的类型

  1. TransportNodesListGatewayMetaState.Request

获取各个节点的元信息的请求

2. TransportNodesListGatewayStartedShards.Request

获取started的shard的列表的请求

3. org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequest

获取节点状态的请求,es默认会每隔30s去检查一遍节点的状态

4. org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest

获取索引状态的请求,es默认会每隔30s去检查一遍index的状态

5. org.elasticsearch.action.search.SearchRequest

search query的请求

全文 >>

HAProxy+Keepalive实现HA

keepalive原理可以参考:Ubuntu安装keepalived

  1. 首先需要安装keepalived
1
2
sudo apt-get install keepalived

  1. 编辑 /etc/keepalived/keepalived.conf 配置,参考:16.6 Configuring Simple Virtual IP Address Failover Using Keepalived

master配置

将master的一个网卡的ip绑定到一个虚拟ip上,其中 interface 是绑定的网卡,virtual_ipaddress 是绑定的虚拟ip的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
global_defs {
notification_email {
root@mydomain.com
}
notification_email_from svr1@mydomain.com
smtp_server localhost
smtp_connect_timeout 30
}

vrrp_instance VRRP1 {
state MASTER
# Specify the network interface to which the virtual address is assigned
interface enp3s0
# The virtual router ID must be unique to each VRRP instance that you define
virtual_router_id 41
# Set the value of priority higher on the master server than on a backup server
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass 1066
}
virtual_ipaddress {
10.0.0.100/24
}
}

启动

1
2
sudo service keepalived start

 

全文 >>

Hive学习笔记——在Hive中使用AvroSerde

Hive支持使用avro serde作为序列化的方式,参考:

1
2
3
4
https://cwiki.apache.org/confluence/display/hive/avroserde
https://www.docs4dev.com/docs/zh/apache-hive/3.1.1/reference/AvroSerDe.html
https://github.com/jghoman/haivvreo

以及CDH官方的文档

1
2
https://docs.cloudera.com/documentation/enterprise/6/6.3/topics/cdh_ig_avro_usage.html

  

1.定义avro schema,kst.avsc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"namespace": "com.linkedin.haivvreo",
"name": "test_serializer",
"type": "record",
"fields": [
{ "name":"string1", "type":"string" },
{ "name":"int1", "type":"int" },
{ "name":"tinyint1", "type":"int" },
{ "name":"smallint1", "type":"int" },
{ "name":"bigint1", "type":"long" },
{ "name":"boolean1", "type":"boolean" },
{ "name":"float1", "type":"float" },
{ "name":"double1", "type":"double" },
{ "name":"list1", "type":{"type":"array", "items":"string"} },
{ "name":"map1", "type":{"type":"map", "values":"int"} },
{ "name":"struct1", "type":{"type":"record", "name":"struct1_name", "fields": [
{ "name":"sInt", "type":"int" }, { "name":"sBoolean", "type":"boolean" }, { "name":"sString", "type":"string" } ] } },
{ "name":"union1", "type":["float", "boolean", "string"] },
{ "name":"enum1", "type":{"type":"enum", "name":"enum1_values", "symbols":["BLUE","RED", "GREEN"]} },
{ "name":"nullableint", "type":["int", "null"] },
{ "name":"bytes1", "type":"bytes" },
{ "name":"fixed1", "type":{"type":"fixed", "name":"threebytes", "size":3} }
] }

将schema文件其放到HDFS上

1
2
3
4
hadoop fs -ls /user/hive/schema
Found 1 items
-rw-r--r-- 3 hive hive 1131 2021-12-04 13:53 /user/hive/schema/kst.avsc

2.建Hive表

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE default.kst
PARTITIONED BY (ds string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
TBLPROPERTIES (
'avro.schema.url'='hdfs:///user/hive/schema/kst.avsc');


全文 >>

Java抽象类与接口的关系

 

 

1.抽象类:

Java可以创建一种类专门用来当做父类,这种类称为“抽象类”。

“抽象类”的作用类似“模板”,其目的是要设计者依据它的格式来修改并创建新的类。但是不能直接由抽象类创建对象,只能通过抽象类派生出新的类,再由它来创建对象。

抽象类的定义及使用规则:

<1>包含一个抽象方法的类必须是抽象类

<2>抽象类和抽象方法都要使用abstract关键字声明

<3>抽象方法只需声明而不需要实现

全文 >>

Java工厂设计模式

工厂模式的核心思想就是把创建对象和使用对象解藕,由工厂负责对象的创建,而用户只能通过接口来使用对象,这样就可以灵活应对变化的业务需求,方便代码管理、避免代码重复。

1.工厂设计模式的例子:水果,苹果和橘子#

程序在接口和子类之间加入一个过渡类,通过此过渡类端取得接口的实例化对象,一般都会称这个过渡端为工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
interface Fruit{
public void eat();
}

// Apple类实现了Fruit接口
class Apple implements Fruit{

@Override
public void eat() {
System.out.println("eat apple!");
}

}

// Orange类实现了Fruit接口
class Orange implements Fruit{

@Override
public void eat() {
System.out.println("eat orange!");
}

}

// 定义工厂类
class Factory{
public static Fruit getInstance(String className){
Fruit f = null; //定义接口对象
if("apple".equals(className)){ //判断是哪个类的标记
f = new Apple();
}
if("orange".equals(className)){ //判断是哪个类的标记
f = new Orange();
}
return f;
}
}

public class factory {

public static void main(String[] args) {
Fruit f = null; //定义接口对象
f = Factory.getInstance("apple"); //通过工厂取得实例
f.eat(); //调用方法
}

}

2.将反射应用在工厂模式上#

为了能不修改工厂方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
interface Fruit{
public void eat();
}

class Apple implements Fruit{

@Override
public void eat() {
System.out.println("eat apple!");
}

}

class Orange implements Fruit{

@Override
public void eat() {
System.out.println("eat orange!");
}

}

// 定义工厂类
class Factory{
public static Fruit getInstance(String className){
Fruit f = null; //定义接口对象
try{
f = (Fruit)Class.forName(className).newInstance(); //实例化对象
}catch(Exception e){
e.printStackTrace();
}
return f;
}
}

public class factory {

public static void main(String[] args) {
Fruit f = null; //定义接口对象
f = Factory.getInstance("Apple"); //通过工厂取得实例
f.eat(); //调用方法
}

}

3.结合属性文件的工厂模式#