实现继承
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{}
AbstractStringBuilder
扩容
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
append(直接在尾部)
添加 字符数组
public AbstractStringBuilder append(char str[]) {
int newCount = count + str.length;
if (newCount > value.length)
expandCapacity(newCount);
System.arraycopy(str, 0, value, count, str.length);
count = newCount;
return this;
}
// 添加 boolean
public AbstractStringBuilder append(boolean b) {
if (b) {
int newCount = count + 4;
if (newCount > value.length)
expandCapacity(newCount);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else {
int newCount = count + 5;
if (newCount > value.length)
expandCapacity(newCount);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}
// 添加 Integer
public AbstractStringBuilder append(int i) {
if (i == Integer.MIN_VALUE) {
append("-2147483648");
return this;
}
int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
: Integer.stringSize(i);
// 需要知道Integer字符串所需长度,因为插入是从尾部开始向前插,
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;
}
// Integer的getchar
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Generate two digits per iteration
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
// r 是后两位
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
// 一次获取两位。。
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
// 不是直接/10
q = (i * 52429) >>> (16+3);
// 不是直接取余
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
insert (允许指定插入位置)
// 在value[]的下标为index位置插入数组str的[offset,offset+len)部分;
public AbstractStringBuilder insert(int index, char str[], int offset,
int len)
{
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
// 腾出 len 的空余长度 ,将count - index 长度的挪到后面
System.arraycopy(value, index, value, index + len, count - index);
// 插入数据
System.arraycopy(str, offset, value, index, len);
count = newCount;
return this;
}
replace 修改
// replace(int start, int end, String str):
// 用字符串str替换掉value[]数组的[start,end)部分
public AbstractStringBuilder replace(int start, int end, String str) {
// 保证不越界
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (start > count)
throw new StringIndexOutOfBoundsException("start > length()");
if (start > end)
throw new StringIndexOutOfBoundsException("start > end");
if (end > count)
end = count;
int len = str.length();
// 替换后的长度
int newCount = count + len - (end - start);
if (newCount > value.length)
expandCapacity(newCount);
System.arraycopy(value, end, value, start + len, count - end);
str.getChars(value, start);
count = newCount;
return this;
}
index(找到子串下标)
// fromIndex开始,在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标
public int indexOf(String str, int fromIndex) {
return String.indexOf(value, 0, count,
str.toCharArray(), 0, str.length(), fromIndex);
}
// lastIndexOf(String str, int fromIndex):从后往前到fromIndex,找子串str
public int lastIndexOf(String str, int fromIndex) {
return String.lastIndexOf(value, 0, count,
str.toCharArray(), 0, str.length(), fromIndex);
}
// string的 indexof
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
// 查子串的终点
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
// 找到第一个首节点
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
// 查询起始点
int j = i + 1;
// 查询结束点
int end = j + targetCount - 1;
// 判断当前 index 是否
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
方法
大多数直接使用抽象父类的方法 少部分抽象方法重写
//abstractstringbuilder
public abstract String toString();
// StringBuilder
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
// StringBuffer
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
synchronized 关键字
修饰实例方法 对当前实例加锁
修饰静态方法 对当前类对象加锁
修饰代码块 对指定对象加锁
相关的一些 wait、notify、notifyAll(object 的方法)
因为synchronized 就是对 对象进行加锁,
// 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
// 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中
// 链接:https://www.zhihu.com/question/37601861/answer/145545371
// 假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.
// notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。notifyAll 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。如果当前情况下有多个线程需要被唤醒,推荐使用notifyAll 方法。比如在生产者-消费者里面的使用,每次都需要唤醒所有的消费者或是生产者,以判断程序是否可以继续往下执行。
public final native void notify();
public final native void notifyAll();
// 让持有对象锁的线程准备释放对象锁权限,释放cpu资源并进入等待
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}
public class sychronized_demo implements Runnable{
public void run() {
}
public static class WaitAndNotify {
public static void main(String[] args) {
Object co = new Object();
System.out.println(co);
for (int i = 0; i < 5; i++) {
MyThread t = new MyThread("Thread" + i, co);
t.start();
}
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("-----Main Thread notify-----");
synchronized (co) {
// 如果是notify, 只有一个线程从等待池进入锁池,然而只有在锁池才能竞争锁
// 等待池中的线程不会去竞争该对象的锁
// 所以如果竞争到锁的进程 执行后续代码 没有notify函数,其他线程就会在 等待池 卡住
co.notifyAll();
}
MyThread t = new MyThread("Thread88" , co);
t.start();
TimeUnit.SECONDS.sleep(2);
System.out.println("Main Thread is end.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread {
private String name;
private Object co;
public MyThread(String name, Object o) {
this.name = name;
this.co = o;
}
@Override
public void run() {
System.out.println(name + " is waiting.");
try {
synchronized (co) {
co.wait();
System.out.println(this.name+" is awaken");
}
System.out.println(name + " has been notified.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}