新时代码农
未读在 Java 开发中,我们经常需要进行字符串的拼接和处理集合中的元素。此外,在某些特定场景下,如性能监控或代码调试时,也需要查看 GC 日志以及字节码信息。本文将详细介绍这些常用技术及其最佳实践。
字符串拼接方法使用 org.apache.commons.lang.StringUtils 拼接123import org.apache.commons.lang3.StringUtils;String result = StringUtils.join(array, "-");
该方法使用指定的分隔符(如这里的’-‘)将数组中的元素连接成一个字符串。
使用 Google Guava 的 Joiner 类12import com.google.common.base.Joiner;String result = Joiner.on('-').join(array);
Guava 库提供的Joiner类可以更加灵活地拼接字符串,支持多种分隔符和自定义转换函数。
获取集合中的第一个元素使用 Iterables.getOnlyElement 方法12im ...
新时代码农
未读本文将详细介绍几种常见的 Java 编程技术及其相关知识点,并提供一些最佳实践和注意事项。这些内容包括面向切面编程(AOP)、使用 Jackson 进行泛型反序列化、单次执行逻辑的实现方法,以及防止主线程退出等。
面向切面编程 (Aspect-Oriented Programming, AOP)代码片段展示1234567891011try { try { doBefore(); // 对应@Before注解的方法切面逻辑 method.invoke(); } finally { doAfter(); //对应@After注解的方法切面逻辑 } doAfterReturning(); //对应@AfterReturning注解的方法切面逻辑} catch (Exception e) { doAfterThrowing(); // 对应@AfterThrowing注解的方法切面逻辑}
解释与注意事项AOP 是一种编程范式,用于将横切关注点 ...
Java 8 引进了强大的 Stream API,使得集合操作更加简洁优雅。本文将详细介绍如何使用 Java 8 的 Stream API 进行 List 转 Map、List 排序、列表过滤及 Map 中的条件操作。
使用 Java 8 Lambda 将 list 转为 map常用方式要将一个 List 转换为 Map,我们可以利用 Collectors.toMap() 方法。例如:
123public Map<Long, String> getIdNameMap(List<Account> accounts) { return accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsername));}
收集成实体本身 map有时候我们可能希望将列表中的对象直接映射到 Map 中作为值,可以这样做:
123public Map<Long, Account> getIdAccountMap(List<Account> a ...
AI:人工智能
未读Zookeeper 是 Google 的 Chubby 一个开源的实现,是 Hadoop 的分布式协调服务
自 2010 年 10 月升级成 Apache Software Foundation(ASF) 顶级项目
分布式协调服务, 提供以下功能:
组管理服务
分布式配置服务
分布式同步服务
分布式命名服务
谁在使用 Zookeeper开源软件
HBase 开源的非关系型分布式数据库
Solr Apache Lucene 项目的开源企业搜索平台
Storm 分布式计算框架
Neo4j 高性能的,Nosql 图形数据库
…
公司
Yahoo
LinkedIn
Twitter
Taobao
…
Zookeeper 架构
客户端随机连接集群中的任何一台 server
集群内所有的 server 基于 Zab(ZooKeeper Atomic Broadcast) 协议通信
集群内部根据算法自动选举出 leader, 负责向 follower 广播所有变化消息
集群中每个 follower 都和 leader 通信
follower 接收来自 leader 的所有变化消息, ...
Python 面向对象基础部分
中秋在家没事, 写了一个很久以前就想写的脚本
如果下午 6 点 10 分还连接着公司的 wifi, 就发邮件给老婆说要加班
为什么要发邮件而不发短信呢, 因为短信接口要钱….最近买了个 4k 的显示器, 拿来外接 mac 看代码, 爽翻了, 不过有点蛮烦的就是每次都要拖动鼠标到另一个屏幕上去, 不过全国最大的同性交友网站 GitHub上面有一款开源的软件叫 CatchMouse 解决了这个问题
下载地址: CatchMouse
另一个问题是如果想把软件从 mac 屏幕放到外接显示屏的话, 还是要拖过去, 但是….另一款神器 Moon 能帮我们快速的把当前应用移动到外接显示器上,
光标定位到需要移动的 app 上, 快捷键 contro+` 即可
接下来是脚本
我的思路是:
先检测当前连接的是哪里的 wifi如果是公司的 wifi, 且当前时间大于 6 点 10 分, 则给老婆发送邮件如果连接的是家里的 wifi, 则检测是否连接了外接显示器,如果连接了, 则检测是否开启了 CatchMouse.app, 没有则打开.
接下来开始撸代码:
1 ...
ERROR: Permission to ArrayDsj/git-test.git denied to dong4j.fatal: Could not read from remote repository.
Please make sure you have the correct access rightsand the repository exists.
目前有 2 个 github 账号, 一个公司的 gitlab 账号
有一次遇到了
1ERROR: Permission to XXX.git denied to user
错误, 整理了一下,这里做一个记录
错误前提很久以前使用 ssh-keygen 生成一对默认名称的公私匙, 直接导入 github 中就能使用, 这是只在一个用户的情况下, 后台又申请了一个 github 账号, 还是使用 id_rsa.pub 这个默认的公匙, 这就造成了上面的错误.
解决方法为不同的账号生成不同的公私匙
1. 生成密匙对
1234567891011# 生成密匙对 名称为 user1-github-ssh-keyss ...
当程序使用某个类时, 如果该类还没被初始化, 加载到内存中, 则系统会通过加载、连接、初始化三个过程来对该类进行初始化. 该过程就被称为类的初始化
类加载指将类的 class 文件读入内存, 并为之创建一个 java.lang.Class 的对象
类文件来源
从本地文件系统加载的 class 文件
从 JAR 包加载 class 文件
从网络加载 class 文件
把一个 Java 源文件动态编译, 并执行加载
类加载器通常无须等到“首次使用”该类时才加载该类, JVM 允许系统预先加载某些类
类加载器类加载器就是负责加载所有的类, 将其载入内存中, 生成一个 java.lang.Class 实例. 一旦一个类被加载到 JVM 中之后, 就不会再次载入了.
根类加载器(Bootstrap ClassLoader): 其负责加载 Java 的核心类, 比如 String、System 这些类
拓展类加载器(Extension ClassLoader): 其负责加载 JRE 的拓展类库
系统类加载器(System ClassLoader): 其负责加载 CLASSPA ...
介绍 Java 内存模型 3 大核心
原子性
可见性
顺序性
原文出处 https://segmentfault.com/a/1190000000435392
并发编程模型的分类在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。
在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写 - 读内存中的公共状态来隐式进行通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。
同步是指程序用于控制不同线程之间操作发生相对顺序的机制。在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。
Java 的并发采用的是共享内存模型,Java 线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。如果编写多线程程序的 Java程序员不理解隐式进行的线 ...
“异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。
同步调用下面通过一个简单示例来直观的理解什么是同步调用:
定义 Task 类,创建三个处理函数分别模拟三个执行任务的操作,操作消耗时间随机取(10 秒内)
123456789101112131415161718192021222324252627@Componentpublic class Task { public static Random random =new Random(); public void doTaskOne() throws Exception { System.out.println("开始做任务一"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); l ...
我们在工作中有时候可能会遇到这样场景,需要在退出容器的时候执行某些操作。SpringBoot 中有两种方法可以供我们来选择(其实就是 spring 中我们常用的方式。只是 destory-method 是在 XML 中配置的,SpringBoot 是去配置化。所以这里就不提这种方式了),一种是实现 DisposableBean 接口,一种是使用@PreDestroy 注解。OK,下面我写两个例子看一下:
DisposableBean 接口我们可以通过实现这个接口来在容器退出的时候执行某些操作。例子如下:
123456789101112131415161718@Componentpublic class TestImplDisposableBean implements DisposableBean, ExitCodeGenerator { @Override public void destroy() throws Exception { System.out.println("<<<<<<&l ...
在大部分时候,我们讨论 API 的设计时,会从功能的角度出发定义出完善的,易用的 API。而很多时候,非功能需求如安全需求则会在很晚才加入考虑。而往往这部分会涉及很多额外的工作量,比如与外部的 SSO 集成,Token 机制等等。
这篇文章会以一个简单的例子,从应用程序和部署架构上分别讨论几种常见的模型。这篇文章是这个系列的第一篇,会讨论两个简单的主题:
基于 Session 的用户认证
基于 Token 的 RESTful API(使用 Spring Security)
使用 Session由于 HTTP 协议本身是无状态的,服务器需要某种机制来区分每个请求。比如在返回给客户的响应中加入一些 ID,客户端再次请求时带上这个 ID,这样服务器就可以区分出来每个请求,并完成事务性的操作(完成订单的创建,更新,商品派送等等)。
在多数 Web 容器中,这种机制通过 Session 来实现。Web 容器会为每个首次请求创建一个 Session,并将 Session 的 ID 以浏览器 Cookie 的方式返回给客户端。客户端(常常是浏览器)在后续的请求中带上这个 Session 的 ID ...
写 Java 程序时会经常从 classpath 下读取文件, 是时候该整理一下了, 并在不断深入的过程中, 陆续补充上.
现在 Java project 都以 maven 项目居多, 比如像下面这样的一个项目结构:
编译后的 class 文件都到了 target 目录, 如下面的结构:
看代码:
123456789101112131415161718192021222324import java.io.File;import java.net.URL;public class Poem { public static void main(String[] args) { Poem poem = new Poem(); poem.getFile("extObj.txt"); } private void getFile(String fileName) { ClassLoader classLoader = getClass().getClassLoader( ...
有时候,系统需要处理非常多的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长。而且当线程数量太多时,系统不一定能受得了。
使用线程池主要为了解决一下几个问题:
通过重用线程池中的线程,来减少每个线程创建和销毁的性能开销。
对线程进行一些维护和管理,比如定时开始,周期执行,并发数控制等等。
ExecutorExecutor 是一个接口,跟线程池有关的基本都要跟他打交道。下面是常用的 ThreadPoolExecutor 的关系。
Executor 接口很简单,只有一个 execute 方法。
ExecutorService 是 Executor 的子接口,增加了一些常用的对线程的控制方法,之后使用线程池主要也是使用这些方法。
AbstractExecutorService 是一个抽象类。ThreadPoolExecutor 就是实现了这个类。
ThreadPoolExecutor构造方法ThreadPoolExecutor 是线程池的真正实现,他通过构造方法的一系列参数,来构成不同配 ...
总结线程池的使用方式
Java 通过 Executors 提供四种线程池, 分别为:
newCachedThreadPool 创建一个可缓存线程池, 如果线程池长度超过处理需要, 可灵活回收空闲线程, 若无可回收, 则新建线程.
newFixedThreadPool 创建一个定长线程池, 可控制线程最大并发数, 超出的线程会在队列中等待.
newScheduledThreadPool 创建一个定长线程池, 支持定时及周期性任务执行.
newSingleThreadExecutor 创建一个单线程化的线程池, 它只会用唯一的工作线程来执行任务, 保证所有任务按照指定顺序 (FIFO, LIFO, 优先级) 执行.
线程池比较单线程的优势在于:
重用存在的线程, 减少对象创建、消亡的开销, 性能佳.
可有效控制最大并发线程数, 提高系统资源的使用率, 同时避免过多资源竞争, 避免堵塞.
提供定时执行、定期执行、单线程、并发数控制等功能.
newCachedThreadPool
12345678910111213141516public static void main(Stri ...