精华内容
下载资源
问答
  • 本书精心编排知识点,从正确的使用习惯开始,让你从“以为自己会Word”,成为“真正的Word 达人”,从而让你在职场更高效、更专业。 Chapter1 大众误区:为什么我用起来会费劲? 1 1.1 Word那么强,你却把它当...
  • 微信公众号:IT一刻钟 大型现实非严肃主义现场 一刻钟与你分享优质技术架构与见闻,一个有剧情的程序员 关注可第一时间了解更多精彩...当JVM启用了偏向锁模式(JDK6以上默认开启),新创建对象的Mark Word中的T...

    微信公众号:IT一刻钟
    大型现实非严肃主义现场
    一刻钟与你分享优质技术架构与见闻,做一个有剧情的程序员
    关注可第一时间了解更多精彩内容,定期有福利相送哟。

    话说有这么一件事。
    在这里插入图片描述
    在这里插入图片描述
    于是当天夜里,小哥哥便哼哧哼哧的画出了偏向锁的逻辑图。
    其逻辑呢,各位看官待我慢慢道来。

    看一张大图

    (点击看大图)
    在这里插入图片描述

    流程讲解

    当JVM启用了偏向锁模式(JDK6以上默认开启),新创建对象的Mark Word中的Thread Id为0,说明此时处于可偏向但未偏向任何线程,也叫做匿名偏向状态(anonymously biased)。

    偏向锁逻辑:
    1.线程A第一次访问同步块时,先检测对象头Mark Word中的标志位是否为01,依此判断此时对象锁是否处于无所状态或者偏向锁状态(匿名偏向锁);

    2.然后判断偏向锁标志位是否为1,如果不是,则进入轻量级锁逻辑(使用CAS竞争锁),如果是,则进入下一步流程;

    3.判断是偏向锁时,检查对象头Mark Word中记录的Thread Id是否是当前线程ID,如果是,则表明当前线程已经获得对象锁,以后该线程进入同步块时,不需要CAS进行加锁,只会往当前线程的栈中添加一条Displaced Mark Word为空的Lock Record中,用来统计重入的次数(如图为当对象所处于偏向锁时,当前线程重入3次,线程栈帧中Lock Record记录)。
    在这里插入图片描述
    退出同步块释放偏向锁时,则依次删除对应Lock Record,但是不会修改对象头中的Thread Id;

    注:偏向锁撤销是指在获取偏向锁的过程中因不满足条件导致要将锁对象改为非偏向锁状态,而释放是指退出同步块时的过程。

    4.如果对象头Mark Word中Thread Id不是当前线程ID,则进行CAS操作,企图将当前线程ID替换进Mark Word。如果当前对象锁状态处于匿名偏向锁状态(可偏向未锁定),则会替换成功(将Mark Word中的Thread id由匿名0改成当前线程ID,在当前线程栈中找到内存地址最高的可用Lock Record,将线程ID存入),获取到锁,执行同步代码块;

    5.如果对象锁已经被其他线程占用,则会替换失败,开始进行偏向锁撤销,这也是偏向锁的特点,一旦出现线程竞争,就会撤销偏向锁;

    6.偏向锁的撤销需要等待全局安全点(safe point,代表了一个状态,在该状态下所有线程都是暂停的),暂停持有偏向锁的线程,检查持有偏向锁的线程状态(遍历当前JVM的所有线程,如果能找到,则说明偏向的线程还存活),如果线程还存活,则检查线程是否在执行同步代码块中的代码,如果是,则升级为轻量级锁,进行CAS竞争锁;

    注:每次进入同步块(即执行monitorenter)的时候都会以从高往低的顺序在栈中找到第一个可用的Lock Record,并设置偏向线程ID;每次解锁(即执行monitorexit)的时候都会从最低的一个Lock Record移除。所以如果能找到对应的Lock Record说明偏向的线程还在执行同步代码块中的代码。

    7.如果持有偏向锁的线程未存活,或者持有偏向锁的线程未在执行同步代码块中的代码,则进行校验是否允许重偏向,如果不允许重偏向,则撤销偏向锁,将Mark Word设置为无锁状态(未锁定不可偏向状态),然后升级为轻量级锁,进行CAS竞争锁;

    8.如果允许重偏向,设置为匿名偏向锁状态,CAS将偏向锁重新指向线程A(在对象头和线程栈帧的锁记录中存储当前线程ID)

    9.唤醒暂停的线程,从安全点继续执行代码

    以上便是偏向锁的整个逻辑了。

    延申知识

    批量重偏向与批量撤销
    渊源:从偏向锁的加锁解锁过程中可看出,当只有一个线程反复进入同步块时,偏向锁带来的性能开销基本可以忽略,但是当有其他线程尝试获得锁时,就需要等到safe point时,再将偏向锁撤销为无锁状态或升级为轻量级,会消耗一定的性能,所以在多线程竞争频繁的情况下,偏向锁不仅不能提高性能,还会导致性能下降。
    于是,就有了批量重偏向与批量撤销的机制。

    解决场景:
    批量重偏向(bulk rebias)机制是为了解决:一个线程创建了大量对象并执行了初始的同步操作,后来另一个线程也来将这些对象作为锁对象进行操作,这样会导致大量的偏向锁撤销操作。
    批量撤销(bulk revoke)机制是为了解决:在明显多线程竞争剧烈的场景下使用偏向锁是不合适的。

    原理:
    以class为单位,为每个class维护一个偏向锁撤销计数器,每一次该class的对象发生偏向撤销操作时,该计数器+1,当这个值达到重偏向阈值(默认20)时,JVM就认为该class的偏向锁有问题,因此会进行批量重偏向。
    每个class对象会有一个对应的epoch字段,每个处于偏向锁状态对象的Mark Word中也有该字段,其初始值为创建该对象时class中的epoch的值。
    每次发生批量重偏向时,就将该值+1,同时遍历JVM中所有线程的栈,找到该class所有正处于加锁状态的偏向锁,将其epoch字段改为新值。下次获得锁时,发现当前对象的epoch值和class的epoch不相等,那就算当前已经偏向了其他线程,也不会执行撤销操作,而是直接通过CAS操作将其Mark Word的Thread Id 改成当前线程Id。
    当达到重偏向阈值后,假设该class计数器继续增长,当其达到批量撤销的阈值后(默认40),JVM就认为该class的使用场景存在多线程竞争,会标记该class为不可偏向,之后,对于该class的锁,直接走轻量级锁的逻辑。

    在这里插入图片描述

    展开全文
  • 老大怎么回事,怎么做项目评估的?只会说相信你可以做的,试一下,有的是时间!  用java开发一个图文处理工具,类似word,任意位置插入、拖动、删除图片以及文本等。文本框、流程图等,数据保存数据库,其余可保存...

           我那个草了!老大怎么回事,怎么做项目评估的?只会说相信你可以做的,试一下,有的是时间!

           用java开发一个图文处理工具,类似word,任意位置插入、拖动、删除图片以及文本等。文本框、流程图等,数据保存数据库,其余可保存pdf格式。ok,姐姐千辛万苦,用swing,没用第三方控件啊,纯java,跨平台!差不多做完了。

            这会儿好了,还要做文件恢复,数据保存到数据库,保存的文件要做二次编辑?在设计得软件上做二次编辑!这有多难?如果说是保存成常用格式的文件,做文件恢复,那程序得读文件的数据,各种图、文字、怎么读?即便是读到了,那哪些数据该放在哪个位置,鬼知道!只能说在保存的时候把所有的组件,数据记录下来。用swing,设想一下,那么程序上每插入的组件我都需要记录,这算法有多难?这个应用的程序界面是一个有固定表头的容器,很大的空白区域,用户可以插入文本,插入图片,插入流程图。使用swing,jform为顶级父类容器,jpanel来作为container.在容器中插入文本,文本使用jtextpane,插入图片用jpanel来承载,而流程图使用jpanel中的paintComonent方法中,绘制Graphical2D来绘制特殊的图形,比如说带箭头的线,菱形、椭圆等。要做文件恢复,那么在文件保存的时候我得记录下所有的组件的属性。简单的说一个文本框jtextpane,文本框的坐标点,大小需要记录,装在哪个父类容器需要记录,在哪个层需要记录。文本框的边框颜色,文本框里面的文字,文字的格式风格需要记录,每个字都要记录啊,可能用户会把部分文字加粗了。然后我才能根据数据恢复一个小小的文本框。恢复一个文本框,还要给她添加监听噢!不然不能编辑啊!怎么可能?是可以实现,人家word可以,ppt可以,ps可以,各种编辑器都可以!sorry啊,我不可以!

            师父已经提交辞职申请了,公司做java的只剩下我了,本来就打算7月离职,这分明是要拿个破东西给你整,整出来了,捡个大便宜!整不出不怪你,要的是你留下来。因为公司还有好多个用java的实现的系统需要人维护,这司马昭之心太明显!这师父也是半路出家搞了差不多一年java。所以这一年,所有东西都是自学,没半个人带啊!虽然说大把时间自己琢磨,我不知道是不是没抓到重点!上半年主要搞java-web,依葫芦画瓢,SSH跨架下编辑出货合同管理系统。逻辑比较简单,刚开始学,还是相当满足的!顺带学android,给公司开发了个离职E化的APP,CS模式。平板上以图文方式秀数据。用了achartengine来做柱状图,广播实现定点自动重启,还有一些图片切换!网络的话用http来来发起数据请求以及响应。服务器端用servlet,自己配色的数据呈现,做出来也蛮开心的。没用这半年就开发这个桌面应用程序,用swing,几乎从头开始学,现在对java-bean 以及监听机制理解更深了!我可以换个更好的工作咩?

    展开全文
  • 许多项目在他们的使用协助/说明网页链接了本指南,这么很好,我们也鼓励大家都这么。但如果你是负责管理这个项目网页的人,请在超链接附近的显著位置上注明: 本指南不提供此项目的实际支持服务! 我们已经...
  • 比如若在第二章的第一张图(图2-1)前插入一张图,则原来的图2-1变为2-2,2-2变为2-3,…,更糟糕的是,文档还有很多对这些编号的引用,比如“流程图见图2-1”。如果图很多,引用也很多,想象一下,手工修改...
  • springfox 接口

    2021-05-09 09:41:55
    现在的技术发展还是很迅猛...当年从北京回武汉,在公司接触了CMMI5,明白应该按照规范的流程做事情,因为那个是最佳实践的沉淀,接口文档用word写的很清楚,通讯协议、入参、出参、加密方式、签名方式、调用时序都要

    现在的技术发展还是很迅猛,子曰:“志于道,据于德,依于仁,游于艺”,既然当年弃工程力学转向软件这个行业,就需要“游”于各种技术之中,虽然年长了,但还是应该熟悉这些新兴的技术,“自古美女如良将,不许人家到白头”,技术人员及时走到管理岗位又怎么样,庞统一天治理一个县城,那是基本功,这些基本功怎么能因为你到了管理岗位就可以不学呢?
    当年从北京回武汉,在公司接触了CMMI5,明白应该按照规范的流程做事情,因为那个是最佳实践的沉淀,接口文档用word写的很清楚,通讯协议、入参、出参、加密方式、签名方式、调用时序图都要写的很清楚,如果有改动怎添加修订记录,做的不好的情况,就是接口文档可能会比较滞后,不过那个时候还是ssm框架,不是前后端分离,冲突还不是那么明显,只有对外接口采用postman等调试一下,接口想对较少。
    现在前端采用vue、react,后端采用springboot,前后端分离,开发工程师也分工了,这个时候矛盾就出来,这个时候yapi、metersphere等工具诞生了,不过这些还不够,还希望通过swagger在代码中就把接口文档写好,这样不是更好吗,再往后发展又诞生了springfox,就这个环节又简化了。

    <springfox.version>3.0.0</springfox.version>
            <spring-plugin.version>2.0.0.RELEASE</spring-plugin.version>
            
     <dependency>
                <groupId>org.springframework.plugin</groupId>
                <artifactId>spring-plugin-core</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.plugin</groupId>
                <artifactId>spring-plugin-metadata</artifactId>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-boot-starter</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.plugin</groupId>
                        <artifactId>spring-plugin-core</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.springframework.plugin</groupId>
                        <artifactId>spring-plugin-metadata</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    springfox-boot-starter默认引用的是1.2.0.RELEASE,启动的时候会提示下面的错误,故而需要调整为2.0.0.RELEASE

    Caused by: java.lang.NoSuchMethodError: org.springframework.plugin.core.PluginRegistry.getPluginFor(Ljava/lang/Object;)Ljava/util/Optional;
    	at springfox.documentation.schema.plugins.SchemaPluginsManager.viewProvider(SchemaPluginsManager.java:95)
    	at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.viewForReturn(OperationModelsProvider.java:116)
    	at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.collectFromReturnType(OperationModelsProvider.java:85)
    	at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.apply(OperationModelsProvider.java:58)
    	at springfox.documentation.spring.web.plugins.DocumentationPluginsManager.modelContexts(DocumentationPluginsManager.java:160)
    	at springfox.documentation.spring.web.scanners.ApiModelReader.read(ApiModelReader.java:87)
    	at springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:154)
    	at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:67)
    	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.scanDocumentation(AbstractDocumentationPluginsBootstrapper.java:96)
    	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)
    	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)
    	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
    	... 19 common frames omitted
    

    启动工程中,这里的使用@EnableOpenApi,它就找到对应的controller了。

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.oas.annotations.EnableOpenApi;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Contact;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    
    import java.util.ArrayList;
    
    @Configuration
    @EnableOpenApi
    public class SwaggerConfig {
    
        @Bean
        public Docket docket(){
            return new Docket(DocumentationType.OAS_30);
        }
    
        private ApiInfo apiInfo(){
            // 作者信息
            Contact contact = new Contact("dzm","","test@qq.com");
            return new ApiInfo("青丘的接口文档",
                    "项目描述",
                    "1.0",
                    "",
                    contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList());
        }
    }
    
    

    这里还可以通过构造器模式创建信息。

    private ApiInfo apiInfo(){
            // 作者信息
            Contact contact = new Contact("dzm","","test@qq.com");
            return new ApiInfoBuilder().title("青丘接口文档")
                        .description("青丘项目")
                        .contact(contact)
                        .version("1.0.0")
                        .build();
        }
    

    打开页面http://localhost:8188/swagger-ui/index.html,这个端口8188是根据系统的启动端口而定,你的可能是8080
    1
    上面的只要带@RestController或者@Controller,它都会把接口帮我们整理出来
    controller的参数说明

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>3.0.0</version>
    </dependency>
    

    这里@Api 类名、@ApiOperation 方法名、@ApiParam 参数说明 对controller进行描述

    @Api("强弱管理")
    @RequestMapping("api/qiangruo")
    @RestController
    public class QiangRuoController {
        private static Logger log = LoggerFactory.getLogger(QiangRuoController.class);
        @Autowired
        private QiangRuoService qiangRuoService;
    
        @ApiOperation("获取孙海义八字旺衰对象")
        @PostMapping("getShyDto")
        public ShyGenYinDto getShyDto(@ApiParam("八字") @RequestParam("bz") String bz){
            String[] zhus = bz.split(" ");
            BaZi bazi = new BaZi.Builder()
                    .setYear(zhus[0]).setMonth(zhus[1]).setDay(zhus[2]).setHour(zhus[3])
                    .build();
            return qiangRuoService.getShyDto(bazi);
        }
    

    返回参数,这里有两个注解@ApiModel 实体类、@ApiModelProperty 实体类属性

    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    
    @Data
    @ApiModel("孙海义根印")
    public class ShyGenYinDto {
    
        /**
         * 年支
         */
        @ApiModelProperty("年支")
        private String yz;
    

    接着就可以看到中文的注释了。
    1
    生产环境不想让别人看到接口文档,于是增加相应的配置

    springfox:
      documentation:
        swagger-ui:
          enabled: false
    
    

    1
    这些还不够,可以通过设置账号、密码,这样还可以查看当前系统的接口版本。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    

    springboot1和springboot2是不一样的,因为我接触的时候已经是springboot2,哪些过去时学习也没啥意义了。
    参考springboot + spring security + swagger 整合

    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableWebSecurity
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        /**
         * 静态资源配置
         * @param web
         * @throws Exception
         */
        @Override
        public void configure(WebSecurity web) throws Exception {
            //swagger2所需要用到的静态资源,允许访问
            web.ignoring().antMatchers("/v3/api-docs",
                    "/swagger-resources/configuration/ui",
                    "/swagger-resources",
                    "/swagger-resources/configuration/security",
                    "/swagger-ui.html");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    //允许根路径url的访问
                    .antMatchers("/").permitAll()
                    //允许swagger-ui.html访问
                    .antMatchers("/swagger-ui.html").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .logout().permitAll()
                    .and()
                    .formLogin().permitAll();
        }
    }
    
    

    启动的时候,打印日志Using generated security password: 71c3ad59-a36c-46e0-be57-1445fb41dff8,这个是密码,用户名为user
    swagger-ui不友好,这里调整一下使用swagger-bootstrap-ui看看,依赖的是springfox-swagger22.9.2,并不是3.0.0,还是有兼容性问题

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'swaggerBootstrapUiResourceExtController' defined in URL [jar:file:/D:/repository/com/github/xiaoymin/swagger-bootstrap-ui/1.9.6/swagger-bootstrap-ui-1.9.6.jar!/com/github/xiaoymin/swaggerbootstrapui/web/SwaggerBootstrapUiResourceExtController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'swaggerResourcesExtProvider' defined in URL [jar:file:/D:/repository/com/github/xiaoymin/swagger-bootstrap-ui/1.9.6/swagger-bootstrap-ui-1.9.6.jar!/com/github/xiaoymin/swaggerbootstrapui/service/SwaggerResourcesExtProvider.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.github.xiaoymin.swaggerbootstrapui.service.SwaggerResourcesExtProvider]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: springfox.documentation.schema.ClassSupport.classByName(Ljava/lang/String;)Lcom/google/common/base/Optional;
    	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:729)
    	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$144/146403516.getObject(Unknown Source)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
    

    后面作者改版了, knife4j
    添加,单体springboot引入下面这个就可以

    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>3.0.2</version>
    </dependency>
    

    这个时候输入http://localhost:8188/doc.html,即可,这种模式就好多了
    1
    这里再做一下测验,看swagger还能做什么

    @ApiOperation("测试")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "day", value = "日柱",required=true)
        })
        @PostMapping("test")
        @ResponseBody
        public ResponseResult<ShyGenYinDto> test(BaZi bazi){
            ResponseResult<ShyGenYinDto> resp = new ResponseResult<ShyGenYinDto>(true);
            return resp;
        }
    
    

    1
    2
    入参为列表的

    import org.springframework.web.bind.annotation.RequestBody
    
    @ApiOperation("批量新增期初明细")
        @PostMapping("addBatch")
        public ResponseResult addBatch(@ApiParam(name = "req",value = "期初明细") @RequestBody List<AccInitialSubjectReq> req){
            return null;
        }
    
    展开全文

空空如也

空空如也

1 2 3 4 5
收藏数 97
精华内容 38
关键字:

word中流程图怎么做