Springboot Iusse List

1.No converter found for return value of type

reason:如果你想通过controller返回JSON对象给你前端,那么必须为该对象的属性添加get方法
solution: 添加get方法

2.Invalid statement(not found)

reason: mybatis mapper文件中的sql语句不正确
solution:修改mapper文件

3.使用 @ControllerAdvice以及 @ExceptionHandler 能不或来自controller层的异常,但是postman的response body不是与其格式.

像如下代码

@ControllerAdvice
public class ExceptionAspect {
  @ExceptionHandler({NewsCategoryExistedException.class, InvalidParamException.class})
  public ApiDto handleException(Exception e){
    return new ApiDto(e.getMessage());
  }
}

当捕获异常后应该返回ApiDto类,但是postman却显示一下内容

{
  "timestamp": "2019-10-15T08:23:02.825+0000",
  "status": 404,
  "error": "Not Found",
  "message": "新闻分类名称已存在",
  "path": "/newsCategory/add"
}

原因:虽然handleException返回的时ApiDto类型,但是该方法并未被标记REST方法,所以返回值不能直接转换成JSON
solution:1 声明该类时同时使用@ControllerAdviceResponseBody ;2 使用 @RestControllerAdvice来声明

小结:如果postman返回404错误,就目前的case来看,是返回给前端的方法未被声明为REST类型,此时注意添加@ResponseBody,或者具有同等作用的annotation,比如@RestControllAdvice

4.在mybatis中使用in

场景:将id为2,3的对象的parentId修改为2

<update id="updateCategoryParent" >
   update news_category set parentId = #{newParentId} where id in
     <foreach collection="oldChildrenIds" item="item" index="index" open="(" separator="," close=")">
       #{item}
     </foreach>
</update>

注意上面的oldChildrenIdsnewParentId,它必须跟dao对象中的参数名一致
void updateCategoryParent(String[] oldChildrenIds, int newParentId);

5.Springboot中的路径
resources/templates
resources/static
在使用Springboot进行web开发时,会发现上面的两个文件夹:templates和static。关于这两个文件夹的使用,还是有些地方需要注意:
如果你是用了Thymeleaf引擎,而且在application.properties中没有设置spring.thymeleaf.prefix,那么thymeleaf会默认在templates中查到文件,例如index.html,然后根据Controller返回的view名字来呈现页面,如下:

@Controller
public class HomeController {

  @Value("${site.title}")
  private String message;

  @RequestMapping("/")
  public String home(Model model){
    model.addAttribute("message",message);
    return "index";
  }
}

注意此时的HomeController声明为@Controller,而不是@RestController,因为我们要返回一个视图,不是简单的JSON数据
但是现在主流的是采用前后端分离技术,也就是说,Controller层只返回数据,不返回视图,这样会带来一个问题,在页面跳转时会发生404错误,例如,在templates文件夹下有如下文件
templates/
–home.html
–news/
——category.html
当我不采用前后端分离,而是在Controller直接返回视图时,我在home.html中使用<a href="news/list">新闻列表</a> 可以直接访问到category.html,注意此时controller中的返回的视图名称时news/list
而当采用前后端分离时,即使你使用<a href="news/category.html">新闻列表</a>也提示找不到页面
此时的解决方案可以这样,创建一个views文件夹,然后把templates中的文件目录拷贝到views下面,然后在application.properties中添加如下设置
spring.thymeleaf.prefix=classpath:/views/
注意views后面必须要带/,此时你就可以使用<a href="news/category.html">新闻列表</a>了,但是带来的不便就是你需要使用ajax来获取REST API返回的数据来填充视图了,而不像上面home方法中所示那样方便处理
所以任何事情都是有利有弊,关键在于你如何平衡,或者说你真正想要是什么

线程安全

定义线程安全是一件相当费劲的事。简单在谷歌上一搜,就出现大量的定义,比如:
1. 线程安全代码就是当多个线程同时执行时也能正常工作的代码
2. 如果以多个线程同时执行仍能保证正确的方式来管理共享的数据结构,那么我们就说代码块是线程安全的
还有一些类似的定义。
你不觉得上述定义等于啥也没说吗,甚至让你更加困惑。我们不能排除掉这些定义,毕竟它们不是错误的。但是事实上它们没有提供任何实际帮助和观点。如何区别线程安全类和非线程安全类?“安全”到底意味着什么?

线程安全中的正确性

所有合理的多线程定义都是“正确性”的概念,因此理解线程安全的前提就是这个“正确性”。

正确性意味着类符合它的规范

当特定的操作作用于类时,一个好的类规范将会包含任意时刻类的状态以及后置条件。由于我们常常不能给出完整的类规范,我们怎么可能知道它们是正确的呢?我们不知道,但即使这样,一旦我们确信“这些代码好使”,我们仍然会使用它们。这种 “代码自信” 跟我们想要的正确性很接近(This “code confidence” is about as close as many of us get to correctness.)
上面已经乐观地将“正确性”定义为可被识别的东西,现在让我们以一种直接的方式来定义线程安全:当被多个线程访问仍然保持正确的行为,那么,我们说这个类是线程安全的。

一个类是安全的,就是当它被多个线程访问,且无论运行环境如何调度,交替执行这些线,它都能保持正确的行为,并且调用方代码无需额外的同步或其他条件。

如果这种宽泛的“正确性”让你很烦躁,你可以将线程安全理解为相比于单线程环境,并发环境并没有给类本身带来更多破坏。线程安全类封装了所需的同步,因此客户端无需再提供。

示例:无状态的Servlet

线程安全类的一个很好示例就是java servlets,它没有任何字段及对其他类的引用等,它们是无状态的

public class StatelessFactorizer implements Servlet{
  public void service(ServletRequest req,ServletResponse resp){
    BigInteger i = extractFromRequest(req);
    BigInteger[] factors = factor(i);
    encodeIntoResponse(resp,factors);
  }
}

特定计算的瞬时状态仅存在于本地变量,而本地变量仅存储在执行线程的栈里,因此它只对执行线程可见。当一个线程访问StatelessFactorizer时,不影响另一个线程的访问,因为两个线程没有任何共享的状态,就像他们访问不同的实例。因为一个线程访问一个无状态类不影响另一个线程操作的正确性,所以无状态类是线程安全的。
以上就是关于这个很小但很重要的线程安全相关的概念
快乐学习!!


译者注:以下为一些精彩评论:
Ramakrishna:
如果参数类型是基本类型,那么每个线程在自己的栈里维护这些变量,如果一个方法引用另一个对象作为参数,那么每个线程仍然在自己线程栈中维护这些对象的状态吗?
Rajesh:
对象的状态总是保存在堆上而非栈,如果你在方法内部引用其他对象,在这种情况下每个线程都会有自己的一份拷贝,因此是线程安全的。

并发的演变

Anant,我的读者之一,问了一个嘎嘎好的问题:是否可以详细说明多线程包括java 8中的相应改进的相关主题(从入门高阶)。他想要的就是从简单的Runnable接口到java 8最新特性的多线程演变过程,我今天就满足他。
我费了九牛二虎之力终于收集到了以下信息,如果哪里不太完善,请愉快的通知我(反正我也不改)。

JDK中的多线程概念

JDK1.x版本里只有很少的类出现。具体的接口/类如下:

  • java.lang.Thread
  • java.lang.ThreadGroup
  • java.lang.Runnable
  • java.lang.Process
  • java.lang.ThreadDeath
  • 以及一些异常类,例如
  1. java.lang.IllegalMonitorStateException
  2. java.lang.IllegalStateException
  3. java.lang.IllegalThreadStateException

除此之外还有一丢丢的同步集合,例如java.util.Hashtable
JDK 1.2和1.3 在多线程这块没什么显著改变(如果有什么出入请更正)
JDK 1.4,只有一点JVM层面关于单次(single call)调用挂起(suspend)/恢复(resume)多线程的改动
JDK 1.5 算是一个大的改动,它融入了多线程并发的各种辅助类:Executor,semaphore,mutex,barrier,latches,concurrent collections 以及 blocking queues,所有的这些都被包含在了这个版本中,java多线程应用云的巨大改变正是孕育于此。

完整的变更列表看这里:http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html

JDK 1.6 相比于API的升级更多的是平台的修复,因此在这个版本中出现了一些新的API
JDK 1.7 增加对ForkJoinPool的支持,ForkJoinPool通过实现工作-窃取(work-stealing)技术来打到最大吞吐量,Phaser类也被引入
JDK 1.8 你懂的 Lambda的引入,然而在并发这块仍然没有太大改动,只有2个接口和4个类引入到了java.util.concurrent包,比如CompletableFutureCompletionException
在java 8 中,为了增加基于新添加的stream功能和lambda表达式的聚合操作,集合框架经历了一次大的修订,因此大量方法被几乎全部引入到了Collection类中,也包括并发集合。

完整的变更列表看这里:http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html

参考:

  • https://www.cs.princeton.edu/courses/archive/fall97/cs461/jdkdocs/relnotes/intro.html
  • http://programmers.stackexchange.com/questions/147205/what-were-the-core-api-packages-of-java-1-0
  • http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html
  • http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/changes7.html
  • http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
  • http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html

希望上述列表能帮助你理解多线程特征的JDK版本指导
译者注:网友在评论区内的补充
1.7
TransferQueue, ConcurrentLinkedDeque, and ThreadLocalRandom

  • https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TransferQueue.html
  • https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadLocalRandom.html
  • https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html

并发和并行

并发意味着在重叠的时间周期内,多个任务以无序的方式启动,运行及完成。并行则是多个任务或者某一任务的不同部分以字面意思同时运行,比如在一个多核的处理上运行。记住,并行和并发不是一件事。
让我们深入的了解一下我所说的并发和并行。

并发

并发本质上应用于我们所讨论的最少两个任务或多任务。当一个应用可以几乎同时地执行两个任务,我们说它是并发程序。虽然两个任务看上去同时运行,但实际上可能并不是。它们利用操作系统CPU时间片的特性,运行任务的一部分,然后进入等待状态,当第一个任务进入等待状态,CPU被分配给第二个任务来完成它的特定部分。
基于优先级的操作系统,分配CPU和其他计算资源例如内存,轮流执行所有的任务,从而让这些任务有机会完成。对于最终用户来说,看起来所有的任务在并行运行。这就叫做并发。

并行

并行并不一定需要存在两个任务,借助于多核架构CPU,它将每个核分配给一个任务或子任务,从而实现物理地同时运行任务的多个部分或多个任务。
实际上,并行依赖多处理单元的硬件支持。而用单核CPU,你可能能得到并发,但是不可能得到并行。

并发与并行的不同

现在,让我们列出两个最明显的不同:
并发两个任务在重叠的时间周期内启动,运行及完成
并行是任务真实地同时运行,例如在多核处理器上。
并发是各独立执行过程的组合,而并行是同时执行的(可能有关)的计算。
并发是一次能处理多件事情,而并行是一次多个事情。
如果一个应用程序是并发但不是并行,那么意味着它虽然可以处理多个任务,但是在某一个时间点任务并不是同时运行
如果一个应用程序是并行但不是并发,那么意味着它在多核的CPU中同时执行某一任务的多个子任务。
如果一个应用程序既不是并行也不是并发,那么意味着在每个时间点顺序执行一个任务
如果一个应用程序既是并行又是并发,那么意味着它利用多核同时执行多个任务
以上就是并发和并行,在java多线程中一个非常重要的概念


译者注:
根据作者的表式,并行和并发的核心区别就是并行是真的有多核/CPU在运行多个任务,而并发则是某个时刻只有一个任务在执行。作者在文章里还区别了任务和子任务,感觉不是很有必要,这只是划分粒度的不同,你认为的子任务在别人眼里可能就是任务。引入任务和子任务反而引起更多的困惑。大家可以参考这片知乎文章:https://www.zhihu.com/question/33515481 比较同意观点:
李遥:

不要把事情说得那么复杂:
并发就是指代码逻辑上可以并行,有并行的潜力,但是不一定当前是真的以物理并行的方式运行
并发指的是代码的性质,并行指的是物理运行状态

黑板客

并发是指同时有很多事要做,你可以串行处理也可以并行处理。
并行是指同时做多件事。
因此并发和并行是相关的,但是是不同的两个概念

Java比较和交换示例-CAS算法

最好的java5新特性之一就是在类中引入原子操作,例如AtomicIntegerAtomicLong等等。针对一些基本操作,这些类帮你简化了多线程代码的复杂性,例如对多线程共享的数据进行增加和减少操作。这些类在内部依赖一个名叫CAS(compare and swap)的算法。在这篇文章中,我将深入的讨论这个概念。

1.乐观锁与悲观锁

对于传统的锁机制,例如在java中使用synchronized,它是一种悲观的锁或多线程技术。它首先就要保证没有其他线程干扰特定的操作(例如:给一个对象加锁)然后只允许你(译者注:当前线程)访问其实例或方法。

就像说“先把门关上,否则其他的骗子会乱动你的东西”

虽然上述方法安全有效,但是在性能方面却挖了个大坑。原因就是等待线程除了获得机会去运行受保护的操作外什么也干不了。
有一种更有效的方法,它天生乐观.在该方法里,你处理一个更新操作,并希望能不受干扰地完成它。该方法依靠冲突检测来决定是否有来自其他部分的干扰,当更新失败时能够重试(与否)。

乐观方法正应了那句老话:获得原谅容易,获得许可难。在这里“容易”意味着“更有效”
译者注:作者采用类比,将乐观锁比作原谅,因为乐观锁就是假设当前没有其他线程的干扰。然后还是不太理解这句老话跟本文主旨的联系

无志者常立志

 无志者常立志就是说的我这种人吧,三十五岁,正好活在IT行业的坎上,高不成低不就,真心焦虑a啊,可除了努力仿佛也找不出更好的办法,那问题来了,努力的方向,未来人工智能技术将会更加普及,所以大方向还得跟上时代潮流啊,这是个中期目标,但是现在就得准备。

 短期目标就是的换工作,首选大厂,当然也有一些创业公司,但是像我这样上有老,下有小的人,真心的慎重啊,万一没挑好就衰了,毕竟没有年龄优势了。进大厂才更有机会在实战中接触到人工智能,但要注意,任何行业发展到成熟阶段必然走向细化,专业化,人工智能也不例外,所以即使选择人工智能,也得把握好方向,这个就因人而异了,我是更倾向于计算机视觉

 想进大厂就得刷题,想在短时间内快速提升,好像没有更好办法,因为国内认这个,如果你是大牛,随时ready,那最好,但我的水平连牛犊子都算不上

 给自己两个月时间,尽可能的多刷吧,暂定每天至少两道吧,贵在坚持。从今天开始我会把每天的任务放在计划的菜单下,并及时总结

2019-08-05 努力成为更好的自己

Oracle linux 常用命令

Vim相关

设置行号:先按Esc 然后输入 :set nu

取消行号:先按Esc 然后输入 :set nonu

全选并删除:先按Esc 然后输入dG

全选:先按Esc 然后输入ggvGggVG. gg:调到首行,V:可视化(高亮),G:到尾行

系统配置

总核数 = 物理CPU个数 X 每颗物理CPU的核数

总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数

查看物理CPU个数
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l

查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo| grep "cpu cores"| uniq

查看逻辑CPU的个数
cat /proc/cpuinfo| grep "processor"| wc -l

wordpress将文章发布到指定链接

刚开始玩wordpress,还不是很溜,首当其冲的是我想建立多个文章类型的页面,然后将不同类型的文章放到不同类型的链接(首页菜单)里。今天终于实现了,其实很简单,两步即可:
1. 点击后台的“文章”链接,添加你想创建的菜单,其实添加分类目录
2. 点击后台的“外观”-“顶部”-“菜单”-“顶部菜单”,然后点击“添加项目”按钮,会列出一些大的分类,然后再“分类目录”里就可以选择你刚创建的分类了
设置好以上两步后,你在创建文章时,可以选择分类,这样就发不到了不同的菜单了