Go race detector

race_detector

线上程序发现处理速度变慢,内存占用变大,后面排查发现 build的时候指定了-race 参数,导致处理速度和内存变大。
正确使用方法是:在运行测试的时候指定-race,来检查是否存在并发写的情况。不能用于线上程序。

官方文档:

The cost of race detection varies by program, but for a typical program, memory usage may increase by 5-10x and execution time by 2-20x.

The race detector currently allocates an extra 8 bytes per defer and recover statement. Those extra allocations are not recovered until the goroutine exits. This means that if you have a long-running goroutine that is periodically issuing defer and recover calls, the program memory usage may grow without bound. These memory allocations will not show up in the output of runtime.ReadMemStats or runtime/pprof.

参考链接

Golang: Concurrency is Hard; So What Can We Do About It?
SRE: Debugging: Simple Memory Leaks in Go
Does the Go race detector catch all data race bugs?
Race-free doesn’t mean deterministic

final vs static final in java

For final, it can be assigned different values at runtime when initialized. For example

Class Test{
  public final int a;
}
Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Thus each instance has different value of field a.

For static final, all instances share the same value, and can’t be altered after first initialized.

Class TestStatic{
      public static final int a;
}
Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

private final static attribute vs private final attribute
Static vs Instance Variables: Difference?

Spring RestTemplate 消息转换2种使用方式

拦截器

public class MyXmlInterceptor implements ClientHttpRequestInterceptor {

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    ClientHttpResponse response = execution.execute(request, body);
    HttpHeaders headers = response.getHeaders();

    // you'd want to check if the value needs to be changed
    if (headers.containsKey("Content-Type")) {
        headers.remove("Content-Type");
    }

    headers.add("Content-Type", "application/xml");

    return response;
}
RestTemplate t = new RestTemplate();
t.getInterceptors().add(new MyXmlInterceptor());

自定义

RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaType.TEXT_HTML);
jaxbMessageConverter.setSupportedMediaTypes(mediaTypes);
messageConverters.add(jaxbMessageConverter);
restTemplate.setMessageConverters(messageConverters);

Unsafe.park & Object.wait

如果是搞应用程序的程序员,就不应该使用这两种方法中的任何一种。两种都太底层了,建议使用 java.util.concurrent.locks , 毕竟类库的就是让你多快好省的写代码。

park 直接操作线程,线程作为参数直接传入,线程会sleep知道调用了 unpark 方法。这种操作需要明确知道那个线程需要 block/unblock。可以使用 java.util.concurrent.locks.LockSupport 完成操作。

park 操作可以理解为Thread.sleep 操作,不会释放锁资源,使用不当会造成死锁。park 操作能够设置一个 blocker,并通过 getBlocker 获取阻塞的信息,方便做一些调试之类的工作。

wait 操作会释放锁。wait 操作必须在同步语句块。如果不在同步语句块会抛出 IllegalMonitorStateException 异常。使用 notify 和 notifyAll 唤醒线程。

wait用于锁机制,sleep不是,这就是为啥sleep不释放锁,wait释放锁的原因,sleep是线程的方法,跟锁没半毛钱关系,wait,notify,notifyall 都是Object对象的方法,是一起使用的,用于锁机制

It all eventually makes its way down to the OS’s scheduler, which hands out timeslices to processes and threads.

sleep(n) says “I’m done with my timeslice, and please don’t give me another one for at least n milliseconds.” The OS doesn’t even try to schedule the sleeping thread until requested time has passed.

yield() says “I’m done with my timeslice, but I still have work to do.” The OS is free to immediately give the thread another timeslice, or to give some other thread or process the CPU the yielding thread just gave up.

wait() says “I’m done with my timeslice. Don’t give me another timeslice until someone calls notify().” As with sleep(), the OS won’t even try to schedule your task unless someone calls notify() (or one of a few other wakeup scenarios occurs).

Threads also lose the remainder of their timeslice when they perform blocking IO and under a few other circumstances. If a thread works through the entire timeslice, the OS forcibly takes control roughly as if yield() had been called, so that other processes can run.

You rarely need yield(), but if you have a compute-heavy app with logical task boundaries, inserting a yield() might improve system responsiveness (at the expense of time — context switches, even just to the OS and back, aren’t free). Measure and test against goals you care about, as always.

继续阅读“Unsafe.park & Object.wait”