精华内容
下载资源
问答
  • 1. 解决什么问题 让我们先从事务说起,“什么是事务?我们为什么需要事务?”。事务是一组无法被分割操作,要么所有操作全部成功,要么全部失败。我们在开发需要通过事务将一些操作组成一个单元,来保证程序...

    推荐阅读:前阿里P7架构师,分享工作心得及面试经验,助力圆梦大厂

                      阿里P8架构师谈:工作1-5年的Java工程师,怎样提高核心竞争力

                      面试被问高并发,又哑口无言?一次性把并发搞清楚!这样最靠谱

    1. 解决什么问题

    让我们先从事务说起,“什么是事务?我们为什么需要事务?”。事务是一组无法被分割的操作,要么所有操作全部成功,要么全部失败。我们在开发中需要通过事务将一些操作组成一个单元,来保证程序逻辑上的正确性,例如全部插入成功,或者回滚,一条都不插入。作为程序员的我们,对于事务管理,所需要做的便是进行事务的界定,即通过类似begin transactionend transaction的操作来界定事务的开始和结束。

    下面是一个基本的JDBC事务管理代码:

    // 开启数据库连接
    Connection con = openConnection();
    try {
        // 关闭自动提交
        con.setAutoCommit(false);
        // 业务处理
        // ...  
        // 提交事务
        con.commit();
    } catch (SQLException | MyException e) {
        // 捕获异常,回滚事务
        try {
            con.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        // 关闭连接
        try {
            con.setAutoCommit(true);
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    

    直接使用JDBC进行事务管理的代码直观上来看,存在两个问题:

    1. 业务处理代码与事务管理代码混杂;

    2. 大量的异常处理代码(在catch中还要try-catch)。

    而如果我们需要更换其他数据访问技术,例如Hibernate、MyBatis、JPA等,虽然事务管理的操作都类似,但API却不同,则需使用相应的API来改写。这也会引来第三个问题:

    1. 繁杂的事务管理API。

    上文列出了三个待解决的问题,下面我们看Spring事务是如何解决。

    2. 如何解决

    2.1 繁杂的事务管理API

    针对该问题,我们很容易可以想到,在众多事务管理的API上抽象一层。通过定义接口屏蔽具体实现,再使用策略模式来决定具体的API。下面我们看下Spring事务中定义的抽象接口。

    在Spring事务中,核心接口是PlatformTransactionManager,也叫事务管理器,其定义如下:

    public interface PlatformTransactionManager extends TransactionManager {
        // 获取事务(新的事务或者已经存在的事务)
        TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
       throws TransactionException;   
        // 提交事务
        void commit(TransactionStatus status) throws TransactionException;
        // 回滚事务
        void rollback(TransactionStatus status) throws TransactionException;
    }
    

    getTransaction通过入参TransactionDefinition来获得TransactionStatus,即通过定义的事务元信息来创建相应的事务对象。在TransactionDefinition中会包含事务的元信息

    • PropagationBehavior:传播行为;

    • IsolationLevel:隔离级别;

    • Timeout:超时时间;

    • ReadOnly:是否只读。

    根据TransactionDefinition获得的TransactionStatus中会封装事务对象,并提供了操作事务查看事务状态的方法,例如:

    • setRollbackOnly:标记事务为Rollback-only,以使其回滚;

    • isRollbackOnly:查看是否被标记为Rollback-only;

    • isCompleted:查看事务是否已完成(提交或回滚完成)。

    还支持嵌套事务的相关方法:

    • createSavepoint:创建savepoint;

    • rollbackToSavepoint:回滚到指定savepoint;

    • releaseSavePoint:释放savepoint。

    TransactionStatus事务对象可被传入到commit方法或rollback方法中,完成事务的提交或回滚。

    下面我们通过一个具体实现来理解TransactionStatus的作用。以commit方法为例,如何通过TransactionStatus完成事务的提交。AbstractPlatformTransactionManagerPlatformTransactionManager接口的的实现,作为模板类,其commit实现如下:

    public final void commit(TransactionStatus status) throws TransactionException {
        // 1.检查事务是否已完成
        if (status.isCompleted()) {
            throw new IllegalTransactionStateException(
                "Transaction is already completed - do not call commit or rollback more than once per transaction");
        }
    
        // 2.检查事务是否需要回滚(局部事务回滚)
        DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
        if (defStatus.isLocalRollbackOnly()) {
            if (defStatus.isDebug()) {
                logger.debug("Transactional code has requested rollback");
            }
            processRollback(defStatus, false);
            return;
        }
    
        // 3.检查事务是否需要回滚(全局事务回滚)
        if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
            if (defStatus.isDebug()) {
                logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
            }
            processRollback(defStatus, true);
            return;
        }
        
        // 4.提交事务
        processCommit(defStatus);
    }
    

    commit模板方法中定义了事务提交的基本逻辑,通过查看status的事务状态来决定抛出异常还是回滚,或是提交。其中的processRollbackprocessCommit方法也是模板方法,进一步定义了回滚、提交的逻辑。以processCommit方法为例,具体的提交操作将由抽象方法doCommit完成。

    protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
    

    doCommit的实现取决于具体的数据访问技术。我们看下JDBC相应的具体实现类DataSourceTransactionManager中的doCommit实现。

    protected void doCommit(DefaultTransactionStatus status) {
        // 获取status中的事务对象    
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        // 通过事务对象获得数据库连接对象
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Committing JDBC transaction on Connection [" + con + "]");
        }
        try {
            // 执行commit
            con.commit();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not commit JDBC transaction", ex);
        }
    }
    

    commitprocessCommit方法中我们根据入参的TransactionStatus提供的事务状态来决定事务行为,而在doCommit中需要执行事务提交时将会通过TransactionStatus中的事务对象来获得数据库连接对象,再执行最后的commit操作。通过这个示例我们可以理解TransactionStatus所提供的事务状态和事务对象的作用。

    下面是用Spring事务API改写后的事务管理代码:

    // 获得事务管理器
    PlatformTransactionManager txManager = getPlatformTransactionManager();
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    // 指定事务元信息
    def.setName("SomeTxName");
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    // 获得事务
    TransactionStatus status = txManager.getTransaction(def);
    try {
        // 业务处理
    }
    catch (MyException ex) {
        // 捕获异常,回滚事务
        txManager.rollback(status);
        throw ex;
    }
    // 提交事务
    txManager.commit(status);
    

    无论是使用JDBC、Hibernate还是MyBatis,我们只需要传给txManager相应的具体实现就可以在多种数据访问技术中切换。

    小结:Spring事务通过PlatformTransactionManagerTransactionDefinitionTransactionStatus接口统一事务管理API,并结合策略模式和模板方法决定具体实现。

    Spring事务API代码还有个特点有没有发现,SQLException不见了。下面来看Spring事务是如何解决大量的异常处理代码。

    2.2 大量的异常处理代码

    为什么使用JDBC的代码中会需要写这么多的异常处理代码。这是因为Connection的每个方法都会抛出SQLException,而SQLException又是检查异常,这就强制我们在使用其方法时必须进行异常处理。那Spring事务是如何解决该问题的。我们看下doCommit方法:

    protected void doCommit(DefaultTransactionStatus status) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Committing JDBC transaction on Connection [" + con + "]");
        }
        try {
            con.commit();
        }
        catch (SQLException ex) {
            // 异常转换
            throw new TransactionSystemException("Could not commit JDBC transaction", ex);
        }
    }
    

    Connectioncommit方法会抛出检查异常SQLException,在catch代码块中SQLException将被转换成TransactionSystemException抛出,而TransactionSystemException是一个非检查异常。通过将检查异常转换成非检查异常,让我们能够自行决定是否捕获异常,不强制进行异常处理。

    Spring事务中几乎为数据库的所有错误都定义了相应的异常,统一了JDBC、Hibernate、MyBatis等不同异常API。这有助于我们在处理异常时使用统一的异常API接口,无需关心具体的数据访问技术。

    小结:Spring事务通过异常转换避免强制异常处理。

    2.3 业务处理代码与事务管理代码混杂

    在2.1节中给出了使用Spring事务API的写法,即编程式事务管理,但仍未解决“业务处理代码与事务管理代码混杂”的问题。这时候就可以利用Spring AOP将事务管理代码这一横切关注点从代码中剥离出来,即声明式事务管理。以注解方式为例,通过为方法标注@Transaction注解,将为该方法提供事务管理。其原理如下图所示:

    三问Spring事务:解决什么问题?如何解决?存在什么问题?

    声明式事务原理

    Spring事务会为@Transaction标注的方法的类生成AOP增强的动态代理类对象,并且在调用目标方法的拦截链中加入TransactionInterceptor进行环绕增加,实现事务管理。

    下面我们看下TransactionInterceptor中的具体实现,其invoke方法中将调用invokeWithinTransaction方法进行事务管理,如下所示:

    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
            throws Throwable {
    
        // 查询目标方法事务属性、确定事务管理器、构造连接点标识(用于确认事务名称)
        final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    
        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // 创建事务
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                // 通过回调执行目标方法
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // 目标方法执行抛出异常,根据异常类型执行事务提交或者回滚操作
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                // 清理当前线程事务信息
                cleanupTransactionInfo(txInfo);
            }
            // 目标方法执行成功,提交事务
            commitTransactionAfterReturning(txInfo);
            return retVal;
        } else {
            // 带回调的事务执行处理,一般用于编程式事务
            // ...
        }
    }
    

    在调用目标方法前后加入了创建事务、处理异常、提交事务等操作。这让我们不必编写事务管理代码,只需通过@Transaction的属性指定事务相关元信息。

    小结:Spring事务通过AOP提供声明式事务将业务处理代码和事务管理代码分离。

    3. 存在什么问题

    Spring事务为了我们解决了第一节中列出的三个问题,但同时也会带来些新的问题。

    3.1 非public方法失效

    @Transactional只有标注在public级别的方法上才能生效,对于非public方法将不会生效。这是由于Spring AOP不支持对private、protect方法进行拦截。从原理上来说,动态代理是通过接口实现,所以自然不能支持private和protect方法的。而CGLIB是通过继承实现,其实是可以支持protect方法的拦截的,但Spring AOP中并不支持这样使用,笔者猜测做此限制是出于代理方法应是public的考虑,以及为了保持CGLIB和动态代理的一致。如果需要对protect或private方法拦截则建议使用AspectJ。

    3.2 自调用失效

    当通过在Bean的内部方法直接调用带有@Transactional的方法时,@Transactional将失效,例如:

    public void saveAB(A a, B b)
    {
        saveA(a);
        saveB(b);
    }
    
    @Transactional
    public void saveA(A a)
    {
        dao.saveA(a);
    }
    
    @Transactional
    public void saveB(B b)
    {
        dao.saveB(b);
    }
    

    在saveAB中调用saveA和saveB方法,两者的@Transactional都将失效。这是因为Spring事务的实现基于代理类,当在内部直接调用方法时,将不会经过代理对象,而是直接调用目标对象的方法,无法被TransactionInterceptor拦截处理。解决办法:

    (1)ApplicationContextAware

    通过ApplicationContextAware注入的上下文获得代理对象。

    public void saveAB(A a, B b)
    {
        Test self = (Test) applicationContext.getBean("Test");
        self.saveA(a);
        self.saveB(b);
    }
    

    (2)AopContext

    通过AopContext获得代理对象。

    public void saveAB(A a, B b)
    {
        Test self = (Test)AopContext.currentProxy();
        self.saveA(a);
        self.saveB(b);
    }
    

    (3)@Autowired

    通过@Autowired注解注入代理对象。

    @Component
    public class Test {
    
        @Autowired
        Test self;
    
        public void saveAB(A a, B b)
        {
            self.saveA(a);
            self.saveB(b);
        }
        // ...
    }
    

    (4)拆分

    将saveA、saveB方法拆分到另一个类中。

    public void saveAB(A a, B b)
    {
        txOperate.saveA(a);
        txOperate.saveB(b);
    }
    

    上述两个问题都是由于Spring事务的实现方式的限制导致的问题。下面再看两个由于使用不当容易犯错的两个问题。

    3.3 检查异常默认不回滚

    在默认情况下,抛出非检查异常会触发回滚,而检查异常不会。

    根据invokeWithinTransaction方法,我们可以知道异常处理逻辑在completeTransactionAfterThrowing方法中,其实现如下:

    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                             "] after exception: " + ex);
            }
            if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                try {
                    // 异常类型为回滚异常,执行事务回滚
                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    throw ex2;
                }
            }
            else {
                try {
                    // 异常类型为非回滚异常,仍然执行事务提交
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    throw ex2;
                }
            }
        }
    }
    

    根据rollbackOn判断异常是否为回滚异常。只有RuntimeExceptionError的实例,即非检查异常,或者在@Transaction中通过rollbackFor属性指定的回滚异常类型,才会回滚事务。否则将继续提交事务。所以如果需要对非检查异常进行回滚,需要记得指定rollbackFor属性,不然将回滚失效。

    3.4 catch异常无法回滚

    在3.3节中我们说到只有抛出非检查异常或是rollbackFor中指定的异常才能触发回滚。如果我们把异常catch住,而且没抛出,则会导致无法触发回滚,这也是开发中常犯的错误。例如:

    @Transactional
    public void insert(List<User> users) {
        try {
            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
            for (User user : users) {
                String insertUserSql = "insert into User (id, name) values (?,?)";
                jdbcTemplate.update(insertUserSql, new Object[] { user.getId(),
                                                                 user.getName() });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    这里由于catch住了所有Exception,并且没抛出。当插入发生异常时,将不会触发回滚。

    但同时我们也可以利用这种机制,用try-catch包裹不用参与事务的数据操作,例如对于写入一些不重要的日志,我们可将其用try-catch包裹,避免抛出异常,则能避免写日志失败而影响事务的提交。

    参考

     

    1. Spring Framework Documentation——Data Access: https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html

    2. 《Spring揭秘》

    3. 5-common-spring-transactional-pitfalls: https://codete.com/blog/5-common-spring-transactional-pitfalls/

    4. Spring事务原理一探: https://zhuanlan.zhihu.com/p/54067384

     

     

    展开全文
  • 如何解决?应收账款是伴随企业销售行为发生而形成一项债权。因此,应收账款确认与收入确认密切相关。应收账款管理对于企业尤为重要。但是现在很多企业在应收账款管理上还存在一些问题。 1、重销售轻回款...

    应收账款管理存在哪些问题?如何解决?应收账款是伴随企业的销售行为发生而形成的一项债权。因此,应收账款的确认与收入的确认密切相关。应收账款的管理对于企业尤为重要。但是现在很多企业在应收账款的管理上还存在一些问题。

    1、重销售轻回款

    这是很多企业存在的一种现象。许多经营一线人员,甚至是企业高层管理人员往往片面地认为:在激烈的市场竞争中,把产品卖出去是一切工作的龙头,销售才是硬道理,而回款则是以后的事情,是财务部门的事情。由于这种销售至上错位观念的影响,企业的应收账款居高不下,问题越积越重。
    应收账款管理

    2、缺乏风险意识

    很多企业对市场缺少应有的风险意识,对客户的经营状况、客户管理层的品格为人等信息缺少基本的调查了解,盲目赊销放账,最终形成逾期应收账款,甚至产生坏账。还有一些企业,对交易过程中形成的书面凭据缺少法律角度的考虑和设计,导致在应收账款不能回收而诉诸法律时,因证据不足而无法得到法律的保护。

    3、责任不清,互相推诿

    一些企业在应收账款管理方面,内部责任划分不清,销售部门推给财务部门,财务部门又推给销售部门,相互扯皮,推卸责任,导致应收账款缺少及时有效的跟进管理。

    4、应收账款的日常管理工作落实不到位

    有些企业虽然制定了比较完整的应收账款制度,但没有真正落实下来,制度要求和实际完成之间存在很大的差距。主要表现有:没有对客户进行认真的考察、放账控制不严格、对账不及时、对账手续不完善、考核措施执行不到位等。

    5、缺乏有效的跟进手段

    许多应收账款在进入呆滞阶段后,作为债权人,由于缺少一套迅速、果断、力度递进的催收措施,使得呆滞账款长期得不到收回。

    应收账款管理问题如何解决:

    1、客户背景调查和资信评估

    及时准确地了解客户的背景资料是应收账款管理众多环节中不可缺少的首要前提。因为只有掌握了客户的这些基本信息,我们才有可能对客户做出尽可能客观而准确的判断,并进而按照一个统一的衡量标准进行评判,以决定是否可以将该客户作为信用客户。

    2、客户信用标准的评估

    信用标准指给予客户最低的信用条件,包括对客户的最高赊销额度、最长赊销期限、赊欠手续等方面的规定。

    3、完善合同及其他书面约定

    为了明确双方的权利和义务,规范双方的行为,赊销企业和客户之间应该订立相关的书面条约,从而对诸如接收订货、交货签收、款项结算、财务对账等一系列环节做出具体的操作规定。对于赊销方来说,这项工作不仅仅是为了提高工作效率,更是保证应收账款在安全状态下运行的法律保障。

    应收账款管理

    4、应收账款的日常管理

    应收账款一旦形成,企业就必须围绕“保证按期足额回款”这一宗旨而展开工作,这些工作是否真正落实到位,直接影响应收账款的管理成果。这一时期的工作重点概括为以下几个方面:

    (1)对客户经营情况的跟进了解;

    (2)对账手续;

    (3)应收账款信息的内部通报;

    (4)应收账款考核。

    5、建立法律保护体系

    建立健全法律保护体系,尽可能将法律漏洞弥补在寻求法律保护之前。

    以上是关于应收账款管理存在问题和解决方法介绍,希望对大家有所帮助。

    展开全文
  • 苹果智能手机"iPhone 4S"是否解决了上一代机型"iPhone 4"饱受指责天线问题?为了验证这一疑问,《日经电子》请曾在手机公司从事过天线等研究工作的日本拓殖大学教授前山利幸实施了检测。在分析过程,还发现...
  • 我曾经说过,工作中80%的问题都是沟通造成的。绝大部分工作问题,不来自于技能本身,而来自于沟通。 沟通的本质,不是你说了什么,而是别人听懂了什么。但问题是,你怎么确认对方听懂了?沟通真的太难了。 后来,我...

    我曾经说过,工作中80%的问题都是沟通造成的。绝大部分工作问题,不来自于技能本身,而来自于沟通。

    沟通的本质,不是你说了什么,而是别人听懂了什么。但问题是,你怎么确认对方听懂了?沟通真的太难了。

    后来,我慢慢发现,沟通之难,主要源于几个客观存在的基本事实:

    一、沟通困难的三个基本事实

    1. 沟通困难的第一个基本事实:每个人脑海里的信息储备完全不同

    我最近研读了几本脑科学书籍,突然意识到:智商需要重新被定义。智商可能更多是对人的一部分脑力的发掘。相比动物,人脑的可塑性更强。

    但这种可塑性会造成什么问题呢?每个人由于大脑信息储备和处理能力不同,造成大脑塑造结果的巨大差异。一人一世界。不同专业背景、不同职位、不同的成长环境,使得每个人在知识储备、理解力、思考模式上迥异。

    我曾经一度认为自己的沟通还不错,直到做机器人后,遇到了有史以来最大的意见争执。我发现,想要与行业背景不同的人达成一致,非常困难。而这种困难本质上源于各自知识储备的差异及由此形成的思维模式差异,最后造成极大的沟通成本。

    这种争论本质上都源于各自知识储备的差异及由此形成的思维模式差异,最后造成极大的沟通成本。

    • 沟通困难的第二个基本事实:语言传输是有损压缩的

    文字是一种很了不起的语言,它将信息压缩到极小的、可反复被传播的载体,极大地提高了沟通的效率和信息的传播范围,并且得以让人类实现协作,建立共识。

    但文字流承载的信息,极其有限。更重要的事实在于,当双方进行沟通时,说出的任何一段语言,经过压缩后再还原,即信息的处理和接收,又开始依赖于各自的信息储备。

    整个信息从压缩到解压的过程,一定会有损耗。

    同样一个词,放在不同的语言体系,一经压缩传递,意思变化差之毫厘,谬以千里。最怕的就是形容词。不同人看,理解不一样。你觉得的“很多”,在我看来可能就一点点。

    • 沟通困难的第三个基本事实:人太容易进入以自我为中心的思考模式

    每个人都很容易进入以自我为中心的思考模式。这里体现为四种心态:

    • 第一种心态:“默认对方是自己肚子里的蛔虫,你就该懂。”别人如果不懂,就懒得沟通。
    • 第二种心态,“这你应该懂啊,我讲这么清楚你怎么就不懂?”或许,别人只是恰巧比你少参加了一次会而已。
    • 第三种心态更可怕,叫“自尊(自卑)心态”,即“你不理我,我也不理你,我凭什么要找你沟通?”大部分人都折在这种心态了,不经过思考,直接把问题归结于对方。
    • 第四种心态,叫道德制高点。很多人跟我说,“我什么都不图,就图公司能更好”;“我就是想把这件事做好,所以,你们应该理解我”;“我很简单很纯粹,所以这个事儿一定是你们有问题。”

    其实,每个人都有自己的诉求。我们不能简单地用出发点或心理优越感,代替沟通本身的问题。如果没有意识到问题的内核,就容易回避沟通能力不足的问题。回避,意味着不敢直面问题,也意味着问题始终存在。

    二、你必须知道的七个沟通基本原则

    如何避免沟通中的这些问题?我认为,沟通前,我们需要为自己树立一些沟通的基本原则。我根据自己的经验和观察总结了以下几条:

    1. 沟通原则1:信息尽量透明

    一个好的企业,一定要在内部做到信息透明,这样做最大的好处就是降低沟通成本。

    谷歌允许每个员工去查代码,facebook允许每个人可以去查别人的目标,我也花了很大力气督促OA建设,目的都是为了信息透明。

    有人会说,商业机密不会泄露吗?如果你想泄密,就一定有办法。但从概率上去判断,哪件事的损失更大呢?我想,答案很清楚。

    1. 沟通原则2:多倾听,理解对方要表达的

    看一个人会不会沟通,就看他打断别人的次数、从他听人讲话的状态,就可以辨别。

    大部分人不具备倾听的能力。因为一个人的语言输入效率只占用大脑的20%,冗余的80%经常会被很多人用来走神,玩手机或交头接耳等等。听别人讲话的人很多,但拥有倾听能力的人很少。

    倾听的本质其实是让你的大脑高负荷运转,同时顺着主讲人的主线进入别人的世界,理解别人为什么这么讲。拥有这样的能力,绝非易事,必须刻意训练。

    1. 沟通原则3:表述时zoom in和zoom out结合,要有框架描述

    表述时要zoom in(意指细节描述)和zoom out(意指宏观概括)结合,要有框架描述。最怕的是指令型的命令。

    所谓框架描述,即要有战略意图的描述,也要有目标的拆解;不要用形容词,描述越具体、越清晰越好。

    1. 沟通原则4:把沟通本身作为问题,不作立场假设

    当我们与别人一起协作,面对结果和预期不一致时,首先应该思考:双方沟通不到位,而不是“对方就是不干活,跟我对着干”。

    每个人都有做事的驱动力,但我们必须承认:人都是懒惰的,都有理解能力的局限。不要轻易去怀疑别人的立场。一旦进入立场假设,中间的过程就容易被忽略。

    1. 沟通原则5:沟通技巧本身是学问,可以不断提升

    沟通技巧是一门学问,技巧的核心是要高度重视沟通形式。

    电子邮件或微信,不能作为沟通手段,最多作为一种信息的备忘手段。发邮件或微信,不是在沟通,而是在下达指令。更何况,这样的指令,或许别人没看到。

    再者,你是否真有能力,在邮件或微信里,用几行字把问题解释清楚,把诉求阐述明白?最好的方式就是面对面。

    1. 沟通原则6:面对面沟通,效率最高

    我们每天可能有很多会议,但大多数会议效率很低。有时候大家开会,不过是为了刷存在感,为了表达自己在努力工作,并不是为了解决沟通中的问题。

    如果问题很紧急,很重要,最好的方式是直接选择面对面沟通。面对面沟通之前,首先做好充分准备;其次带着问题来;最后,做好会议纪要。如此,效率最高。

    1. 沟通原则7:有反馈的沟通,才是有效沟通

    当你完成一次沟通后,要想办法去拿到别人的反馈。其实就是别人到底听懂了什么。

    这样的反馈,不是拍胸脯说,我懂了。而是沟通完后,他做了一份文档,甚至把刚才沟通的事再讲一遍。本质就是促使他花时间去思考,整理思路,最终将沟通结果做出来。

    以上都是一些比较基本的沟通大原则。但沟通是一个系统工程,要想做到高效沟通,在具体的实际运用中,我们还有很多需要刻意训练的思维和技巧。

    三、如何做到高效沟通呢?

    我从三个维度分别给出解决方案。即做好向下沟通、同级沟通和向上沟通:

    1. 如何高效沟通?之向下沟通

    首先,分享一个网上的段子:

    吃中饭的时候,谷歌CEO说:“我想买摩托罗拉手机”。
    吃晚饭的时候,下属说:“老大,我已经帮你买下来了。”
    CEO问:“哦?哪个型号啊?”
    下属答:“……买下来了,30亿美金……”

    这是上下级之间沟通经常出现的问题。实际工作中,如果上级只是简单的指令表达,在下级的眼里,则完全是另一个词汇。

    当你是一名干部,或者作为管理者,向下沟通是非常重要的工作,有几个点比较重要:

    (1)给予底层信任:充分理解下级的成长诉求

    我刚参加工作不久,带着几个人做360安全卫士,资源有限,招不到人,公司极度不重视,为了调动积极性,我当时总结了一套努力工作的方法。其实,核心就是不断理解下属的诉求。

    虽然那时工资较低,但我告诉他们,至少我能保证你们每一天都在进步,我们可以把工作看成另类的大学。

    所有沟通都是为了成长。这个阶段,底层员工既想成长,又迷茫,某种意义上,他们的上级就是一个传道授业解惑的职场老师。

    (2)传达战略理解:传递公司高层战略和意图

    猎豹发展到今天,这么多年,我始终坚持开放每周公司例会的分享,就是为了让基层员工也能获得最新信息,理解公司的战略和意图。

    这样的传达非常重要。当你把整个公司背景传达给下属后,就是让整个组织效能最大化,让所做的事情事半功倍。

    (3)真正达成共识:把对方当成参与者,而不是简单的执行者;不是简单的下命令,而是充分描述项目框架和具体目标,形成讨论。

    表达意见的核心是为了达成共识。当大家都说出自己的想法,彼此才能相互理解;只有真正理解之后,才有机会达成共识。

    我最常说的一句话叫:多说,婆婆嘴。一件事要反复说,一个公司战略要在不同场合,不同部分,来回说。

    人都有遗忘曲线,没有人会天天思考这些问题。婆婆嘴的一个核心就是要反复多次检查,且检查要密集。沟通要获得具体清晰的正反馈,而不是相信拍胸脯。

    (4)指出问题时,不作定性描述,只描述具体事情

    什么叫定性描述?定性描述就是“XXX,你没有责任心”,描述具体事情就是“XXX,上周六发生了突发事件,可你邮件微信都不回”。这些话一旦说出来,他没法反驳。如果你说别人没责任心,没人会承认。

    不要用形容词,也不要去定性,否则对方很容易产生对抗情绪,一旦对抗,沟通就很难进行下去。

    很多管理者喜欢做酒肉朋友,以后我罩着你之类,这对下属的成长非常不利。你一定要明白,沟通的本质是帮助他完成最底层的成长诉求。很多人跟着一个领导好几年,部门不出绩效,大家也都没有成长,最后其实浪费的是自己的时间。

    作为一个管理者,向下沟通的核心就是:是否愿意花时间去理解下属的成长诉求,去发掘他的成长路径,帮助下属树立一个好的职场成长观,帮助他与自我的一些弱点对抗等等,这都是向下沟通的关键之所在。

    1. 如何高效沟通?之同级沟通

    说完向下沟通,再来说同级沟通。作为管理者,向下沟通的坎,较为容易迈过。面对同级时,反而最容易产生沟通的问题。

    同级沟通中,最典型的一个思维陷阱就是——总有奸臣想害朕。这句话就是一个完全自我为中心的思维状态。

    我见过很多人的思维模式,容易“同行相轻”,瞧不起同级——这帮人太low,我怎么沦落到跟他一起工作,或者,他太复杂,动不动就挑拨离间,向老板献媚等等。

    面对同级,总是一种居高临下的视角。这样的视角,非常非常要命。

    如何才能做好与你同级同事之间的沟通呢?我认为以下几点,比较重要:

    1、理解人欲,理性平等看待对方的诉求

    雷军说过一句话,到了四十岁后,有一个重大的感悟就叫“人欲即天理”。每个人有一些诉求,都是正常的。无所谓谁比谁更高级,要平等理性地看待对方。

    不要本末倒置,把沟通当作核心,沟通只是手段,而要把目标作为核心诉求。当你用目标去驱动自己的沟通时,你就会更好地理解别人,理解沟通的目的。

    2、坦诚表达具体问题,不作暗示

    任何一种沟通,都会触发内心的情绪,导致大多数人很难客观理智地面对沟通。

    当你觉得不满,要直接讲,讲的过程中,可能有一些铺垫,但最终可以发现问题。不要去作暗示,效率太低。

    坦诚是一种力量,让沟通变得更高效,且能跟组织目标集合。我们不用把别人想得很脆弱,担心说这个话,他就跟我闹掰了,退一步讲,如果他跟你闹掰了,说实话,这人的确不值得你交。

    更严重一点,我曾经是鼓励下属去吵架的,当然得就事论事,不准人身攻击。有的时候,冲突或者讨论的激烈,并不是什么坏事情。要相信,对方是成年人。如果说两句就玻璃心,可能我们选拔他就是有问题的。

    3、不作立场假设,控制情绪,只解决沟通问题本身

    当我们在沟通时,一旦沟通遇阻,或者对方有反对意见,就会作立场假设,甚至妄意揣测对方动机。这些做法都是非常低效的。

    沟通的核心点就是要控制情绪,理性表达,多讲具体问题。当具体问题讲多了,大家理解了,自然就变成框架性问题。解决沟通问题本身才是目标,而不是立场假设,作无用功。

    1. 如何高效沟通?之向上沟通

    最后说一下向上沟通。大部分人,都不太不重视与老板的沟通,甚至是退缩,逃避,不沟通。

    向上沟通中,最常见的一种自我开脱的理由就是——老板太忙了!

    首先,理解一下老板是个什么物种。老板不是一个单纯的人的一个存在,更多是一个职位的存在。在工作场合,所谓老板,不管是CEO或部门管理者,如果他越优秀,就越不应该是一个人格意义上的人,而是一个职位意义上的人。

    那么,老板到底是一个什么样的物种呢?

    第一,他未必比你聪明,但一般情况下,他的见识和判断比你强。他的信息渠道优于你,信息质量和数量超过你,犯的错误也比你多,应付过的复杂考验,见过的大场面可能也比你多。

    第二,你的老板会犯错,但他做对的概率比你大。你没有到他的层级,你很难想象他拿到的信息和判断的依据。从对的概率来说,他做出正确判断的概率肯定比你大。

    第三,他很忙,但重要的事情他比你更有时间。每个人都天生认为自己很重要。如果你觉得老板不理你,可能是你表达的东西,他认为不重要,或者你没有让他觉得重要。这还是沟通的问题。

    第四,他的职位要求比你高,所以你认为的重要感受,他往往不在意。经常会有人说,你怎么不理解我。我说你理解我吗?你那点小委屈在我面前光哭诉就要半小时,我哪有那么多时间?所以要找到核心点,不要上来就讲感受,要反向理解。

    第五,他也不是神,很多情况他不知道。最好的办法就是把问题讲出来。有人可能会想,讲出来后,我不成了搬弄是非吗?你倒是想搬弄是非,但你有这能力吗?你也太低估老板的判断力了。不要忌讳说问题。你把信息告诉他后,他自有自己的判断力。

    第六,他是资源的汇聚,说服他就能充分放大你的能量。最大的核心点就是——老板本质上是个资源的汇聚体。你说服他,你的能量可以放大好多倍。

    当然,如果你认为放大能量不重要,只想安静地做一个佛系员工,那么你在公司体系下很难做出有效输出。

    理解了老板是一个什么样的物种后,具体到沟通,应该怎么做呢?我总结了几点:

    (1)老板说的要充分理解,因为可能让你学到更多

    老板对你完成个人目标和个人成长特别有好处。这是一个现实,没什么好抱怨的。他说的话,你真的要充分理解。他的信息和见识一定远远大于绝大部分员工。

    (2)不要用简单的战术问题去和老板的战略意图作对抗

    每个一线员工,肯定有更多的细节执行的知识,这样的知识,老板一定不知道。如果你拿着这些来反驳老板,就会陷入两个不同层级的讨论,这样的讨论得不出有效结果。

    你应该反过来理解——他为什么这么说?他的意图是什么?他看到了什么趋势?我怎么去消化掉?

    还是那句话,他的信息量比你大,你要坚信,他有更大概率做出比你更强的判断。

    (3)放弃封建主义的君臣思想,认为小人才献媚,清者自清

    这一点很重要。即使在古代,皇帝与大臣之间也是有沟通的,只不过载体是奏折。没有沟通,就没有相互理解。如果指望只要做好事情就能被发现,就是没理解什么叫沟通。

    中国人的沟通能力是非常弱的,大家都喜欢推崇一种所谓只可意会不可言传。其实不沟通,都会出问题。

    经常有人说,会哭的孩子有奶喝。但凭什么你就不会哭呢?其实会哭,也是表达自己的一种能力。如果你连表达自己都不会,何谈在公司里好好干活呢?你宅在家里就行了。

    有些人会说清者自清,我不想说,不方便说,不好说,一说就成了搬弄是非的人。还是那句话,你想当小人,哪有那么容易啊?老板是会综合所有信息,一起观察,做判断的人。而你,其实也是老板很重要的调查渠道之一。

    在沟通中,说具体问题是最关键的,老板有他的判断力。如果不能面对具体问题,不管是老板,还是你的同事,甚至下属,这样的人,都不可交。

    (4)说服老板不容易,但很值得,要多花时间

    当你把老板看成一个资源体时,他能有时间和你交流,非常非常难得。很多时候,可能就是几句话,就能解决你的很多问题。

    想想,巴菲特午餐为啥卖那么贵,其实核心就是他的话有着更大的信息量。对一个拥有一定资产的人来说,听他的几句话,就可能带来一个很大的撬动作用。

    四、写在最后

    沟通的目的,其实是让所有人的认知和目标实现统一。这是最难的,也是最重要的。然而,太多人过于简单、粗糙地理解沟通本身。

    太多人低估沟通对自我能力的塑造作用。当你认为别人可以获得更多资源,一定不要简单为:他比我能讲,比我多跟老板干了几年;其实不是,本质他可能整个逻辑思路更强、更清晰、更懂得沟通。

    我们一定要意识到——沟通是一种能力,它并不天然的,而是可以被刻意训练、被学习、被精进的能力。只有如此,你的成长,才可能真正上一个大台阶。

    展开全文
  • 2018-11-07 原来win7下安装的texlive2016,后来卸载升级到2017,出现...但明明cmd运行xelatex命令是存在的,这说明系统路径上可能存在问题。但无法确定什么原因所在,找问题的过程是尝试的过程。 首先在一...

    2018-11-07


    原来win7下安装的texlive2016,后来卸载升级到2017,出现latexmk无法正常工作的情况,继续升级到2018也有类似的问题。
    在另一个笔记本上实验,也有类似的问题。

    问题的表现是latexmk找不到xelatex命令?但明明cmd中运行xelatex命令是存在的,这说明系统路径上可能存在问题。但无法确定什么原因所在,找问题的过程是尝试的过程。

    首先在一个笔记本查看,看路径似乎也没有什么问题,尝试半天找不到原因。

    于是想到能否用.latexmkrc,是不是会有相同的表现的,而且故意把.latexmkrc内容写错,会是什么现象?

    在cmd中运行latexmk,发现这次有了提示,似乎是可以通过tlmgr命令设定perl 路径为texlive所带内部的perl的路径,于是按照提示的命令,运行后发现问题解决。

    latexmk可以使用了。


    我以为另一台式机上也是同样的问题,所以,也没有把笔记本上的命令记录下来。但按照同样的前面的方法,没有得到需要的提示。按照记忆的提示内容进行搜索perl built in tlmgr 等搜索关键词,搜索latexmk文档,帮助,以及tlmgr的帮助也没有找到相似的命令。这次似乎是没有办法了。

    再次分析台式机上的问题,测试错误的.latexmkrc文件也没有特别的提示,主要还是找不到xelatex,biber等命令,那还是路径问题,到底怎么回事呢?

    查看path路径似乎没有问题,但还是要测试,于是利用cmd的set命令临时设置path为简单的texlive 2018的bin路径,发现这时latexmk编译没有问题了,那么只能说明,系统设置的path路径参数中有问题,导致latexmk找不到路径。于是一个一个测试,发现其中有一个带双引号的路径是关键,它导致了后面的texlive 路径似乎没有作用。于是将该路径删除即解决了问题。

    从这里看到,latexmk和cmd寻找路径的机制肯定不同,cmd能正常的搜索的路径,而latexmk则不行,这在以后使用应多加注意。

    展开全文
  • 我曾经说过,工作中80%的问题都是沟通造成的。绝大部分工作问题,不来自于技能本身,而来自于沟通。 沟通的本质,不是你说了什么,而是别人听懂了什么。但问题是,你怎么确认对方听懂了?沟通真的太难了。 后来,...
  • 一、超市库存管理存在的问题目前在许多超市的经营管理过程中存在着库存管理方面的诸多问题,严重影响了超市的库存管理实现合理化和盈利能力的提升,所以我们必须引以足够重视,下面小编给您梳理了一下几个问题:1、...
  • 数据不平衡问题主要存在于有监督机器学习任务。当遇到不平衡数据时,以总体分类准确率为学习目标传统分类算法会过多地关注多数类,从而使得少数类样本分类性能下降。绝大多数常见机器学习算法对于不平衡数据...
  • 在Excel VBA,可以利用Application.Inputbox来选择区域,但是该方法不能够跨工作簿选择。同样,若采用RefEdit控件也存在不能跨工作簿选择的问题。 本文介绍一种替代的方法来跨工作簿选择区域。
  • jar包冲突是一个过程,既存在某种场景使得两个jar包能够互相关联,并且两个jar包会存在对立或不一致内容,并产生相互作用。为什么会有jar包冲突这种问题呢? 假设没有场景联系两个jar包或者关联两个jar包内容...
  • 一、存在的问题 假如我们需要通过开展进行大规模的 App 地推,首先要解决的就是地推人员或地推代理金融机构的业绩评估技术难题,由于没有涉及到对工作研究人员的考核、奖惩、管理,重要性以及自然不言而喻。这就要求...
  • 最近在做项目过程,发现一些问题,于是百度和google,大概知道问题如何解决,但是依然有一些疑惑,又继续网上寻找答案,终究不能解答对问题的疑惑。网上很多博客还有论坛给出答案都惊人相似,但问题的疑惑依旧...
  • jar包冲突是一个过程,既存在某种场景使得两个jar包能够互相关联,并且两个jar包会存在对立或不一致内容,并产生相互作用。为什么会有jar包冲突这种问题呢? 假设没有场景联系两个jar包或者关联两个jar包内容...
  • 当然,一个集群可以存在多少个主要分片是有限制,因此您可能不希望浪费整个分片来仅收集几千个文档。在这种情况下,您可以实现自己自定义type字段,该字段的工作方式与旧类似_type。 让我们以上面user/...
  • 苹果智能手机"iPhone 4S"是否解决了上一代机型"iPhone 4"饱受指责天线问题?为了验证这一疑问,《日经电子》请曾在手机公司从事过天线等研究工作的日本拓殖大学教授前山利幸实施了检测。在分析过程,还发现...
  • 使用POI实现数据页面数据导出,由于页面数据量大,存在八张报表。根据POI方式使用echarts自带图片导出功能,获取到报表Base64码传送到后台写入到excel。但由于图片数据量太大,请求体中的form数据过大,...
  • [导读] LED照明电源设计存在以下几个设计难题:电解电容寿命与LED不相匹配、LED灯闪烁的常见原因与处理办法... 电解电容寿命与LED不相匹配的问题  LED照明的一个重要的考虑因素,就是LED驱动电路与LED本身的工作
  • 浅谈劳动竞赛中存在的问题、原因及对策 中铁十三局二公司工会 开展劳动竞赛是工会工作的重要内容,也是调动和发挥职工积极性和创造性的重要手段。这几年,在各部门的配合下,劳动竞赛在完成生产任务、提高经济效益...
  • 以往,传统招采方式、供应商来源比较单一,线下操作流程复杂,采购周期较长,供应商质量参差不齐,纸张式采购资料无法得到很好汇总和数据分析……很多企业在招采过程,会出现很多问题。首先,无论采用传统...
  • 你有没有碰到这种情况:将Mac...在这里,我们将让您知道Finder继续崩溃时发生了什么,并提供了多种解决问题的解决方案。 一、重新启动查找器 如果Finder崩溃或死机,则应首先尝试强制重新启动。有三种方法可以做到这
  • 现在常用的数字水准仪以自动安平水准仪作为基础,在望远镜添加了分光镜和探测器等,弥补了光学测量仪在测量时存在的测量速度、测量数据的精度、测量质量等方面的不足,高效完成测量工作,通过使用仪器自动显示降低了...
  • 我们在使用的Django的时候需要使用models.py去创建我们的表在sqlite3或者mysql(选择哪种数据库是需要在setting.py进行配置),现在存在的问题就是我们不需要进行新表的创建工作,我们如何直接使用我们mysql已经...
  • 但事实证明编码焦虑是真实存在的。我发现许多学生在学习或者工作一个多小时后便无法集中注意力,在学习和工作的压力让他们筋疲力竭。或许真的有些天赋异禀的人把敲代码当成打游戏,但这种看法其实更多来自不明就里...
  • 大家好,今日讲解VBA数据库解决方案第19讲:如何在数据库新建一个查询表,并在工作显示出来。关于Recorsset集合的一些操作讲解,在前几讲讲了很多,这里提醒大家一点:任何对象都不是孤立存在的,要结合实际来...
  • 有时项目会用到AJAX同步,同步概念是来源于OS中的概念,即不同进程为协同完成某项工作而在先后次序上做了调整,这一点是通过阻塞、唤醒等方式,同步强调是顺序性,异步则不存在这种顺序性。 同步(async值为...
  • CRM背景介绍小企业实施CRM面临... 客户丢失和流失销售人员的变动带来的客户丢失,销售过程的客户流失是每个企业经营者亟需避免的问题。 2. 效率和考核问题如何考核和提高销售人员的工作效率,使您煞费苦心。 3. ...
  • 你有没有碰到这种情况:将Mac更新到了最新macOS,突然Finder开始崩溃,总是意外退出。发生这种情况时,您会在以下弹出窗口...在这里,我们将让您知道Finder继续崩溃时发生了什么,并提供了多种解决问题的解决方...
  • 生产环境解决跨域得问题 如果您在生产环境发现一些重复出现的问题,该怎么办? 好吧,令人惊讶的是,大多数情况下重新启动是可行的,但是如果您要在多个数据中心的100台具有代码的机器上管理10项服务,那么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,234
精华内容 493
关键字:

如何解决工作中存在的问题