初探Java字符串

字符串对象内部是用字符数组存储的

    String m = "hello,world";
    String n = "hello,world";
    String u = new String(m);
    String v = new String("hello,world");

这些语句会发生这么些事情:
1. 会分配一个长度为11的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串
2. 用n去引用常量池里面的字符串,所以和n引用的是同一个对象
3. 生成一个新的字符串,但是内部的字符数组引用着m内部的字符数组
4. 生成一个新的字符串,但是内部的字符数组引用常量池里面的字符串内部的字符数组

字符串常量通常是在编译的时候就确定好的,定义在类的方法区里面;也就是说,不同的类,即使用了同样的字符串,还是属于不同的对象。

字符串的操作细节

    String m = "hello,world";
    String u = m.substring(2,10);
    String v = u.substring(4,7);

m,n,v是三个不同的字符串对象,但引用的value数组其实是同一个。

但是字符串操作时,可能需要修改原来的字符串数组内容或者原数组没法容纳的时候,就会使用另外一个新的数组(例如replaceconcat+等操作)

    String m = "hello,";
    String u = m.concat("world");
    String v = new String(m.substring(0,2));

常量池中字符串的产生

    String m = "hello,world";
    String u = m + ".";
    String v = "hello,world.";

uv虽然是一样的内容的字符串,但是内部的字符数组不是同一个。

如果将m定义为final,编译器就会把u和v做成一样的了。

Reference

http://www.importnew.com/17034.html

2016/2/23 posted in  Java

深入分析Volatile的实现原理

Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的可见性。它在某些情况下比synchronized的开销更小(因为它不会引起线程上下文的切换和调度)。

可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。

Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。Java提供了Volatile,在某些情况下比锁更加方便。如果一个字段被声明成VolatileJava线程内存模型确保所有线程看到这个变量的值是一致的。

Java代码: 
instance = new Singleton();//instance是volatile变量

汇编代码:   
0x01a3de1d: movb $0×0,0×1104800(%esi);
0x01a3de24: lock addl $0×0,(%esp);

volatile变量修饰的共享变量进行写操作的时候会多第二行汇编代码,lock前缀的指令在多核处理器下会引发两件事情:
- 将当前处理器缓存行的数据写回到系统内存
- 这个歇会内存的操作会引起其他CPU里缓存该内存地址的数据无效

处理器为了提高处理速度,不直接和内存进行通讯,而是先将系统内存的数据读到内部缓存(L1L2或其他)后再进行操作,但操作完之后不知道何时会写到内存,如果对声明了volatile变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在的缓存行的数据写回到系统内存。但是就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。

所以在多处理器下,为了保证每个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线程上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自动缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置为无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存把数据读到处理器缓存里。

2016/1/25 posted in  Java

Java Exchanger

The Exchanger class represents a kind of rendezvous point where two threads can exchange objects.

Exchanging objects is done via one of the two exchange() methods.

Exchanger exchanger = new Exchanger();

ExchangerRunnable exchangerRunnable1 =
        new ExchangerRunnable(exchanger, "A");
ExchangerRunnable exchangerRunnable2 =
        new ExchangerRunnable(exchanger, "B");

new Thread(exchangerRunnable1).start();
new Thread(exchangerRunnable2).start();

Here is the ExchangerRunnable code:

public class ExchangerRunnable implements Runnable{

    Exchanger exchanger = null;
    Object    object    = null;

    public ExchangerRunnable(Exchanger exchanger, Object object) {
        this.exchanger = exchanger;
        this.object = object;
    }

    public void run() {
        try {
            Object previous = this.object;

            this.object = this.exchanger.exchange(this.object);

            System.out.println(
                    Thread.currentThread().getName() +
                    " exchanged " + previous + " for " + this.object
            );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

This example prints out:

Thread-0 exchanged A for B
Thread-1 exchanged B for A
2016/1/20 posted in  Java

Java `CyclicBarrier`

The CyclicBarrier class is a synchronization mechanism that can synchronize threads progressing through some algorithm. In other words, it is a barrrier that all threads must wait at, until all threads reach it, before any of the threads can continue.

Creating a CyclicBarrier

CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

Waiting at a CyclicBarrier

Here is how a thread waits at CyclicBarrier:

cyclicBarrier.await();

You can also specify a timeout for the waiting thread. When the timeout has passed the thread is also released, even if not all N thread are waiting at the CyclicBarrier. Here is how you specify a timeout:

cyclicBarrier.await(10, TimeUnit.SECONDS);

CyclicBarrier Action

Runnable barrierAction = ...;
CyclicBarrier barrier = new CyclicBarrier(2, barrierAction);

CyclicBarrier Example

Runnable barrier1Action = new Runnable() {
    public void run() {
        System.out.println("BarrierAction 1 executed ");
    }
};
Runnable barrier2Action = new Runnable() {
    public void run() {
        System.out.println("BarrierAction 2 executed ");
    }
};

CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);

CyclicBarrierRunnable barrierRunnable1 =
        new CyclicBarrierRunnable(barrier1, barrier2);
CyclicBarrierRunnable barrierRunnable2 =
        new CyclicBarrierRunnable(barrier1, barrier2);

new Thread(barrierRunnable1).start();
new Thread(barrierRunnable2).start();   

Here is the CyclicBarrierRunnable class:

public class CyclicBarrierRunnable implements Runnable{

    CyclicBarrier barrier1 = null;
    CyclicBarrier barrier2 = null;

    public CyclicBarrierRunnable(
            CyclicBarrier barrier1,
            CyclicBarrier barrier2) {

        this.barrier1 = barrier1;
        this.barrier2 = barrier2;
    }

    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() +
                                " waiting at barrier 1");
            this.barrier1.await();

            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() +
                                " waiting at barrier 2");
            this.barrier2.await();

            System.out.println(Thread.currentThread().getName() +
                                " done!");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}   

Thread-0 waiting at barrier 1
Thread-1 waiting at barrier 1
BarrierAction 1 executed
Thread-1 waiting at barrier 2
Thread-0 waiting at barrier 2
BarrierAction 2 executed
Thread-0 done!
Thread-1 done!
2016/1/20 posted in  Java

Java CountDownLatch

A CountDownLatch is a concurrency construct that allows one or more threads to wait for a given set of operations to complete.

A CountDownLatch is initialized with a given count. This count is decremented by calls to the countDown() method. Threads waiting for this count to reach zero can call one of the await() methods. Calling await() blocks the thread until the count reaches zero.

Below is a simple example. After the Decrementer has called coundDown() 3 times on the CountDownLatch, the waiting Waiter is released from the await() call.

CountDownLatch latch = new CountDownLatch(3);

Waiter      waiter      = new Waiter(latch);
Decrementer decrementer = new Decrementer(latch);

new Thread(waiter)     .start();
new Thread(decrementer).start();

Thread.sleep(4000);

public class Waiter implements Runnable{

    CountDownLatch latch = null;

    public Waiter(CountDownLatch latch) {
        this.latch = latch;
    }

    public void run() {
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Waiter Released");
    }
}

public class Decrementer implements Runnable {

    CountDownLatch latch = null;

    public Decrementer(CountDownLatch latch) {
        this.latch = latch;
    }

    public void run() {

        try {
            Thread.sleep(1000);
            this.latch.countDown();

            Thread.sleep(1000);
            this.latch.countDown();

            Thread.sleep(1000);
            this.latch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
2016/1/20 posted in  Java