tonglin0325的个人主页

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”异常。

全文 >>

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');


或者直接在TBLPROPERTIES中指定schema

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
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.literal'='{
"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} }
] }');

3.查看Hive表的schema

1
2
describe kst;

全文 >>

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.结合属性文件的工厂模式

全文 >>

Java适配器设计模式

适配器设计模式,一个接口首先被一个抽象类先实现(此抽象类通常称为适配器类,比如下面的WindowAdapter),并在此抽象类中实现若干方法(但是这个抽象类中的方法体是空的),则以后的子类直接继承此抽象类,就可以有选择地覆写所需要的方法。

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
interface Window{					//定义Window接口,表示窗口操作
public void open(); //窗口打开
public void close(); //窗口关闭
public void activated(); //窗口活动
public void iconified(); //窗口最小化
public void deiconified(); //窗口恢复大小
}

abstract class WindowAdapter implements Window{ //定义抽象类实现接口,在此类中覆写方法,但是所有的方法体为空
public void open() {} //窗口打开
public void close() {}; //窗口关闭
public void activated() {}; //窗口活动
public void iconified() {}; //窗口最小化
public void deiconified() {}; //窗口恢复大小
}

class WindowImp1 extends WindowAdapter{ //子类直接继承WindowAdapter类,有选择地实现需要的方法
public void open() { //窗口打开
System.out.println("窗口打开");
}

public void close() { //窗口关闭
System.out.println("窗口关闭");
}
}

public class Adapter_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Window win = new WindowImp1(); //实现接口对象
win.open();
win.close();
}

}

全文 >>

Java自定义异常类

用户可以根据自己的需要定义自己的异常类,定义异常类只需要继承Exception类即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MyException extends Exception{		//自定义异常类,继承Exception类
public MyException(String msg){ //构造方法接受异常信息
super(msg); //调用父类中的构造方法
}
}


//主类
//Function : MyException_demo
public class MyException_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
try{
throw new MyException("自定义异常"); //抛出异常
}catch(Exception e){ //异常处理
System.out.println(e);
}

}

}

全文 >>