深入理解为什么不要使用System.out.println()

一、前言

关于项目中为什么不要使用System.out.println()的解释,网上有很多资料却并不准确或者详细,今天就其原因以及可能对项目造成的影响做深入剖析。

本篇文章氛围三个 要点,源码解析、影响分析、代码演示。

二、源码解析

打开println的源码,看到println方法体中有synchronized,也就是有锁的控制,换而言之就会出现阻塞的可能,后面我们会认为制造阻塞来演示。

如下图:

打开out源码,发现out用final static来修饰,也就是静态变量,可以认为在单机jvm中该变量全局唯一,如下图:

三、影响分析

通过以上两个图,我们可以想到有这么一种场景,在System.out.println()运行过程中,或因系统原因或者其它原因,导致在执行println的时候,发生了阻塞,那么因此带来的后果是,所有使用System.out.println()的地方,都会处于block状态,甚至引发系统宕机等。

至于System.out.println()本身的性能问题,可以作为单纯的性能优化来讲,也是不建议使用,既然是深入分析,我们先看下严重的场景,这才是导致禁用Syste.out.println()的重要原因。

四、代码模拟

我们根据源码,模拟这么一种场景,由于某种原因,System.out处于锁定状态,长时间没有释放,会引发什么。

模拟步骤:

1、新建两个线程:线程一和线程二

2、让线程一和线程二运行三秒后,开始对System.out进行锁定

3、查看线程一和线程二在System.out锁定时的打印情况及线程状态

4、释放System.out锁,在此查看线程一和线程二的运行情况

以下是测试代码:

package com.zhufeng.thread;


public class ZhufengDemo {

    public static Object o = new Object();

    public static void main(String[] args) throws InterruptedException {
        ZhufengThread t1= new ZhufengThread("一");
        ZhufengThread t2= new ZhufengThread("二");

        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);

        thread1.start();
        thread2.start();


        System.out.println("3秒后对 System.out 加锁...");
        Thread.sleep(3000);
        //synchronized ( o){
        synchronized ( System.out){
            System.out.println("已经加锁...");
            for(int i=10;i>0;i--){
                System.out.println("倒计时:"+i+"——线程一状态:"
                        +thread1.getState()+",线程二状态"+thread2.getState());
                Thread.sleep(1000);
            }
        }
        System.out.println("锁已释放...");
    }
}

此处运行逻辑是按照方才的说明步骤进行,线程中仅仅使用System.out.println进行打印,在System.out处于锁定状态时,查看两个线程是否会继续打印

package com.zhufeng.thread;


public class ZhufengThread implements Runnable {

    private String name;
    public ZhufengThread(String name){
        this.name=name;
    }
    @Override
    public void run() {
        while (true){
            System.out.println(name+"线程运行...");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程中每隔1.5秒打印一次。

我们运行打印程序,查看控制台日志:

结论:

通过控制台日志可以看到,线程一和线程二在运行过程中,如果System.out处于锁定时,两个线程处于BLOCKED状态,且不在进行打印,等待10秒System.out锁释放后,又开始重新执行打印。

所以说,生产上如果大量使用System.out.println(),将会对所有使用该语句的逻辑造成阻塞,影响不言而喻。

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链进行发送,直到其中一个处理者能够处理它为止。每个处理者都有一个对下一个处理者的引用,形成了一个链式结构。 这种模式的优点在于它可以动态地组合处理者链,而不需要修改现有代码。它还允许您以灵活的方式为请求选择处理者。 下面是一个简单的Java示例,演示了如何使用责任链模式。我们将创建一个处理器链,每个处理器都能处理特定类型的请求: 首先,我们需要定义一个请求类,它将包含要处理的数据: ```java public class Request { private String requestType; private String requestData; public Request(String requestType, String requestData) { this.requestType = requestType; this.requestData = requestData; } public String getRequestType() { return requestType; } public String getRequestData() { return requestData; } } ``` 接下来,我们需要定义一个处理器接口,它将定义处理请求的方法: ```java public interface RequestHandler { void handleRequest(Request request); } ``` 然后,我们将实现几个具体处理器类,分别处理不同类型的请求: ```java public class EmailHandler implements RequestHandler { private RequestHandler nextHandler; public void setNextHandler(RequestHandler handler) { nextHandler = handler; } public void handleRequest(Request request) { if (request.getRequestType().equals("email")) { System.out.println("EmailHandler handles request: " + request.getRequestData()); } else if (nextHandler != null) { nextHandler.handleRequest(request); } else { System.out.println("No handler found for request: " + request.getRequestType()); } } } public class FaxHandler implements RequestHandler { private RequestHandler nextHandler; public void setNextHandler(RequestHandler handler) { nextHandler = handler; } public void handleRequest(Request request) { if (request.getRequestType().equals("fax")) { System.out.println("FaxHandler handles request: " + request.getRequestData()); } else if (nextHandler != null) { nextHandler.handleRequest(request); } else { System.out.println("No handler found for request: " + request.getRequestType()); } } } public class LetterHandler implements RequestHandler { private RequestHandler nextHandler; public void setNextHandler(RequestHandler handler) { nextHandler = handler; } public void handleRequest(Request request) { if (request.getRequestType().equals("letter")) { System.out.println("LetterHandler handles request: " + request.getRequestData()); } else if (nextHandler != null) { nextHandler.handleRequest(request); } else { System.out.println("No handler found for request: " + request.getRequestType()); } } } ``` 最后,我们将使用这些处理器类创建一个处理器链,并将请求发送到该链: ```java public class ChainDemo { private static RequestHandler getChainOfHandlers() { RequestHandler emailHandler = new EmailHandler(); RequestHandler faxHandler = new FaxHandler(); RequestHandler letterHandler = new LetterHandler(); emailHandler.setNextHandler(faxHandler); faxHandler.setNextHandler(letterHandler); return emailHandler; } public static void main(String[] args) { RequestHandler chain = getChainOfHandlers(); chain.handleRequest(new Request("email", "Email request")); chain.handleRequest(new Request("fax", "Fax request")); chain.handleRequest(new Request("letter", "Letter request")); chain.handleRequest(new Request("unknown", "Unknown request")); } } ``` 当我们运行该程序时,它将输出以下结果: ``` EmailHandler handles request: Email request FaxHandler handles request: Fax request LetterHandler handles request: Letter request No handler found for request: unknown ``` 这个例子演示了如何使用责任链模式来处理请求。在这个例子中,我们创建了一个处理器链,每个处理器都可以处理特定类型的请求。当请求到达链的顶部时,它将沿着链向下传递,直到找到可以处理它的处理器为止。如果没有处理器能够处理请求,则会输出一条错误消息。 总之,责任链模式可以让您以灵活和可扩展的方式组织代码,并将请求发送到处理器链中,直到找到可以处理它的处理器为止。这种模式可以用于许多不同的场景,例如请求处理、日志记录和异常处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月夜烛峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值