每天弄懂三个问题(一)

问题一、String,StringBuffer,StringBuilder的区别?

       String:字符串常量;

       StringBuffer:字符串变量(线程安全)

       StringBuilder:字符串变量(非线程安全)

       速度一般情况下:StringBuilder > StringBuffer > String

       速度区别的主要原因是由于String是不可变的对象,每次针对的String对象的改变都是生成新的String对象,然后将指针指向新生成的对象。这样系统中无引用的String实例越来越多,增加GC的次数,系统自然会慢。

        StringBuffer和StringBuilder的主要区别是StringBuffer是线程安全的,而StringBuilder是非线程安全的,针对它们的字符串操作是在原String对象基础上改变而不是生成新的String对象。因此真对单线程下的String缓冲操作可以使用StringBuilder获得最好的性能,需要注意线程安全的情况下可使用StringBuffer保证线程安全。

       1,特殊情况

 String s1 = “This is only a” + “ simple” + “ test”;
 StringBuilder sb1 = new StringBuilder(This is only a).append(" simple").append(" test");

    生成是s1的速度快的多,那是由于在JVM编译时针对Constant Pool中的常量"+"操作符进行了优化,实际上是

String s1 = "This is only a simple test"

    这样速度当然更快了。当然如果有个String 的引用不是来自Constant Pool,那么JVM就没有优化了,sb1的效率更高。

       2,值得注意的是,下面创建了几个String对象?

String s1 = new String("s1");
String s2 = new String("s1");

     答案:3个,编译期Constant Pool中创建了一个“s1”,运行期heap中创建了两个(new)

问题二、加了static的synchronized方法和不加static的synchronized方法有啥区别?

              针对这个问题我们可以联想加了static的方法和不加static的方法有什么区别,static方法,类的方法,该类的实例和该类均可以调用,非static方法,只有类的实例可以调用,那么很容易知道加了static的synchronized方法和是针对类上了锁,只要有一个类正在访问该方法段,其它实例均需要等待(针对不同实例,锁均有效),而非static的synchronized的方法只是针对实例级别上锁,同一实例不同线程访问,锁有效,针对不同的实例,无锁。

问题三、Java底层是如何操作文件的?

              可以看JDK里面FileInputStream的实现

/**
     * Opens the specified file for reading.
     * @param name the name of the file
     */
    private native void open(String name) throws FileNotFoundException;

    /**
     * Reads a byte of data from this input stream. This method blocks
     * if no input is yet available.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             file is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public native int read() throws IOException;

       都是native方法,因此是依赖操作系统,在windows上调用DLL实现。

          我们可以联想tomcat的bio,nio,apr三种Connector模式,tomcat为了提高吞吐量获得更高的性能可以使用apr,即直接调用native方法进行IO操作发送静态资源,而不是使用Java封装的IO。默认情况下tomcat发送大于48k的静态资源,使用sendFile。sendFile能够避免静态资源在用户态和内核之间的四次copy,直接在内核态将资源写入TCP栈。tomcat设定了一个threshold为48K,48K一下的文件使用缓存的方式性能会更好。

  

猜你喜欢

转载自zwustudy.iteye.com/blog/2034704