欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java技术的那些事

程序员文章站 2022-05-05 08:55:39
...

https://clojars.org/
jar包下载地址

线程
1.实现Runnable接口
implement Runnable 接口
2.任务逻辑代码
Task()

3.重写run函数
override
run()

4.调用:
Thread t = new Thread();
t.start();

工厂模式:
1.定义一个造车接口 CreateCar
2.对这个接口有N个实现,可以造各种品牌的车 BmwCar,beichiCar,LuhuCar,DazhongCar…
3.创建一个工厂factory,把这N种造车的实现都归纳管理起来if()else if(){…}
4.调用工厂factory,给定N个的其中一个参数,可以任性想要制造什么车就定制什么车。

二、单例模式特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
三、线程安全的问题

单例模式:实现单例模式的方式
1.饿汉式单例(立即加载方式)
// 饿汉式单例
public class Singleton1 {
// 私有构造
private Singleton1() {}

private static Singleton1 single = new Singleton1();

// 静态工厂方法
public static Singleton1 getInstance() {
    return single;
}

}
饿汉式单例在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。

2.懒汉式单例(延迟加载方式)
// 懒汉式单例
public class Singleton2 {

// 私有构造
private Singleton2() {}

private static Singleton2 single = null;

public static Singleton2 getInstance() {
    if(single == null){
        single = new Singleton2();
    }
    return single;
}

}
该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个single对象,如何改造请看以下方式:
使用synchronized同步锁
public class Singleton3 {
// 私有构造
private Singleton3() {}

private static Singleton3 single = null;

public static Singleton3 getInstance() {
    
    // 等同于 synchronized public static Singleton3 getInstance()
    synchronized(Singleton3.class){
      // 注意:里面的判断是一定要加的,否则出现线程安全问题
        if(single == null){
            single = new Singleton3();
        }
    }
    return single;
}

}

在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,
但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。

消息队列RockeMQ:

问题复现:

启动消费者1,消费组为group1,订阅topicA的消息,tag设置为tag1 || tag2
启动消费者2,消费组也为group1,也订阅topicA的消息,但是tag设置为tag3
启动生产者,生产者发送含有tag1,tag2,tag3的消息各10条
消费者1没有收到任何消息,消费者2收到部分消息

启动消费者1,消费组为group1,订阅topicA的消息,tag设置为tag1 || tag2
启动消费者2,消费组也为group2,也订阅topicA的消息,但是tag设置为tag3
启动生产者,生产者发送含有tag1,tag2,tag3的消息各10条
消费者1,2各收到全部消息

启动消费者1,消费组为group1,订阅topicA的消息,tag设置为tag1 || tag2
启动消费者2,消费组也为group1,也订阅topicB的消息,但是tagB设置为tag3
启动生产者,生产者发送含有tag1,tag2,tag3的消息各10条
启动消费者2失败(消费组已存在)

启动消费者1,消费组为group1,订阅group1的消息,tag设置为group1
启动生产者,生产者发送含有group1的消息10条
消费者1可以订阅到消息,无丢失

结论:
1.同一个消费组中,设置不同tag时,后启动的消费者会覆盖先启动的消费者设置的tag
2.tag决定了消息过滤的条件,经过服务端和客户端两层过滤,最后只有后启动的消费者才能收到部分消息
3.不同启动相同的消费组
4.不同消费组,同一个消费主题和tag, 均可以消费到所有消息,无丢失.
5.消费者可以订阅group,topic,tag值完全一样的消息,无丢失

实际:
免费版免费版rocketmq 可以动态创建group值,topic值,tag值,互不影响 (可以实现动态订阅)
阿里云rocketmq 可以动态tag值,不可以动态创建topic值,但是订阅时groupID和topic值一样,且必须在订阅组指定groupID值才能正常订阅(不可实现动态订阅)

创建生产者,消费者
ONSFactory.createBatchConsumer()批量消费者
ONSFactory.createOrderedConsumer()顺序消费者
ONSFactory.createOrderProducer() 顺序生产者
ONSFactory.createTransactionProducer() 事务生产者

中间件修改ACL白名单:
/opt/docker_rocketmq/4.5.0/broker-m-1/conf
plain_acl.yml

第一次消费失败,msgExt.getReconsumeTimes()为0,由于原始messageDelayLevel为 “1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”,
当delayLevel为3的情况下,就对应10s,也就是说,第一次消费失败的消息,会在10s后重新消费,依次类推。
消息自第一次消费失败后,由原先的topic转入%RETRY%队列,如果消息消费失败次数大于maxReconsumeTimes(16次),消息会进入DLQ队列。

如果消息重试 16 次后仍然失败,消息将不再投递。如果严格按照上述重试时间间隔计算,某条消息在一直消费失败的前提下,
将会在接下来的 4 小时 46 分钟之内进行 16 次重试,超过这个时间范围消息将不再重试投递。
注意: 一条消息无论重试多少次,这些重试消息的 Message ID 不会改变。

注意:
消息队列服务中若有ACL,那么路由groupPerms:的参数存在的情况下,数据才不会丢失
若路由中group组不存在,生产的消息不会完全被消费

生产者:
1.创建生产者(服务地址,key,groupID)
2.启动生产者 producer.start()
3.创建Message: new Message(topic,tag,body.getBytes())
4.使用producer发送message:producer.send(message)

消费者:
1.创建消费者(服务地址,key,groupID)
2.订阅消息监听 consumer.subscribe(topic,tag,new messageListener())
3.启动订阅 consumer.start()

普通消息,顺序消息,广播模式,集群模式

消息队列禁止使用RocketMQ本身的日志:
System.setProperty(“rocketmq.client.log.loadconfig”, “false”);

运行java的时候日志时间打印设置北京时间:
java -Dfile.encoding=UTF8 -Duser.timezone=GMT+08 -jar /opt/docker_java/abutment-0.0.1.jar >> /opt/docker_java/logs/abutment.log 2>&1

定时任务:
springboot中一个注解就搞定定时任务
@Scheduled(fixedDelay = 1000 * 60 * 20) 每20分钟执行一次
public void startTask(){…业务代码}

Http请求
使用JDK原生提供的net,无需其他jar包;JDK原生态HttpURLConnection实现 和 URLConnection实现
1.创建连接对象
2.设置请求类型
3.设置请求需要返回的类型
4.允许写入,读入,不缓存
5.得到响应结果
6.得到响应流,转换成字符

HttpClient实现:
1.commons-httpclient引用包
2.创建httpClient实例对象
HttpClient httpClient = new HttpClient();
3.设置httpClient连接主机服务器超时时间:15000毫秒
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);
4.创建post请求方法实例对象
PostMethod postMethod = new PostMethod(urlParam);
5.设置post请求超时时间
postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
6.设置Header属性
postMethod.addRequestHeader(“Content-Type”, “application/json”);
7.执行请求
httpClient.executeMethod(postMethod);
8.得到结果
String result = postMethod.getResponseBodyAsString();
postMethod.releaseConnection();

使用JDK原生提供的net,无需其他jar包;Socket实现:

1.https协议
socket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(this.host, this.port);
public void sendGet() throws IOException{
//String requestUrlPath = “/z69183787/article/details/17580325”;
String requestUrlPath = “/”;

    OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());    
    bufferedWriter = new BufferedWriter(streamWriter);              
    bufferedWriter.write("GET " + requestUrlPath + " HTTP/1.1\r\n");    
    bufferedWriter.write("Host: " + this.host + "\r\n");    
    bufferedWriter.write("\r\n");    
    bufferedWriter.flush();    

    BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());    
    bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8"));    
    String line = null;    
    while((line = bufferedReader.readLine())!= null){    
        System.out.println(line);    
    }    
    bufferedReader.close();    
    bufferedWriter.close();    
    socket.close();  

}  

===================================================================================
log4j日志级别
log4j的8个日志级别(OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL)

===================================================================================
GET和post区别“标准答案”:

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST么有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。

相关标签: 亲力亲为