stringbuffer和thread.join对线程控制的问题以及线程协作的问题
1.关于StringBuffer线程安全的问题,如何理解?它的线程安全是控制到什么程度的?
下面的这段代码,输出什么?
public class StringBufferTest {
private static StringBuffer sb = new StringBuffer();
public static void main(String[] args) throws Exception {
Thread t0 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100;i ++) {
sb.append(i+" ");
}
}
};
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100;i ++) {
char c = (char)('a' + i);
sb.append(c+" ");
}
}
};
t0.start();
t1.start();
t0.join();//持有join的线程,会在该线程执行完毕后才能继续往下执行
t1.join();
System.out.println(sb);
}
}
下面的这段代码,输出什么?
public class StringBufferTest {
private static StringBuffer sb = new StringBuffer();
public static void main(String[] args) throws Exception {
Thread t0 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100;i ++) {
sb.append(i+" ");
}
}
};
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100;i ++) {
char c = (char)('a' + i);
sb.append(c+" ");
}
}
};
t0.start();
t1.start();
t0.join();//持有join的线程,会在该线程执行完毕后才能继续往下执行
t1.join();
System.out.println(sb);
}
}
答案:实际的结果是数字和字符打串了
2.如果我想首先打印线程1所有的数字,再打印线程2所有的所有字符,如何改这个代码
Java Thread中, join() 方法主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码。
所以应该为(两个线程顺序执行):
t0.start();
t0.join();
t1.start();
t1.join();
如果为并发执行:
在原来的代码的run(){
synchronized(sb){
for()
}
}
3.如果我想首先打印线程1的一个数字,再打印线程2的一个字符,依次交替打印,如何改这个代码(线程协作)
public class StringBufferTest {
private static StringBuffer sb = new StringBuffer();
private static boolean thread1Run =true;
private static boolean thread2Run = false;
public static void main(String[] args) throws Exception {
Thread t0 = new Thread() {
@Override
public void run() {
for (int i =0 ; i< 100; i++) {
synchronized (sb){
while (!thread1Run) {
try {
sb.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sb.append(i + " ");
thread1Run = false;
thread2Run = true;
sb.notify();
}
}
}
};
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (sb) {
while (!thread2Run) {
try {
sb.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
char c = (char)('a' + i);
sb.append(c + " ");
thread1Run = true;
thread2Run = false;
sb.notify();
}
}
}
};
t0.start();
t1.start();
t0.join();
t1.join();
System.out.println(sb);
}
}
private static StringBuffer sb = new StringBuffer();
private static boolean thread1Run =true;
private static boolean thread2Run = false;
public static void main(String[] args) throws Exception {
Thread t0 = new Thread() {
@Override
public void run() {
for (int i =0 ; i< 100; i++) {
synchronized (sb){
while (!thread1Run) {
try {
sb.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sb.append(i + " ");
thread1Run = false;
thread2Run = true;
sb.notify();
}
}
}
};
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (sb) {
while (!thread2Run) {
try {
sb.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
char c = (char)('a' + i);
sb.append(c + " ");
thread1Run = true;
thread2Run = false;
sb.notify();
}
}
}
};
t0.start();
t1.start();
t0.join();
t1.join();
System.out.println(sb);
}
}
总结:
我们说StringBuffer是线程安全的,不是说它是完全线程安全,即对StringBuffer的任何操作都不需要关心线程安全问题
而是它是部分线程安全,它的线程安全性体现在,调用append的操作时是安全的,因为这个方法加锁了
而是它是部分线程安全,它的线程安全性体现在,调用append的操作时是安全的,因为这个方法加锁了
所以,在两个线程里面同时分别执行sb.append("12345678"),sb.append("abcdef")
不会出现打串的情况
不会出现打串的情况