Java 多线程 系列文章目录:
- Java 多线程(一)线程间的互斥和同步通信
- Java 多线程(二)同步线程分组问题
- Java 多线程(三)线程池入门 Callable 和 Future
- Java 多线程(四)ThreadPoolExecutor 线程池各参数的意义
- Java 多线程(五)Lock 和 Condition 实现线程同步通信
- Java 多线程(六)Semaphore 实现信号灯
- Java 多线程(七)CyclicBarrier 同步的工具类
- Java 多线程(八)CountDownLatch 同步工具类
- Java 多线程(九)Exchanger 同步工具类
- Java 多线程(十)ArrayBlockingQueue 阻塞队列
- Java 多线程(十一)JDK 同步集合
我们都知道传统的线程同步可以通过同步代码块或者同步方法来实现。
那么这里就牵扯到同步监视器的问题。
如果对同步监视器不了解的获取对线程相关知识不了解的, 可以查看博客:http://blog.csdn.net/johnny901114/article/details/7536951
要想确保线程之间能够同步,那么监视器对象对于同步线程之间来说是同一个对象,这样才会起到同步互斥效果。
所以很多人使用字节码(class) 最为同步对象,因为在内存中只存在一份某个类的字节码。 当然这很好,当这是对于一组同步函数而言的。
如果有多组函数呢?既然是多组,那么就有多个同步监视器对象,如果同步监视器使用同一个类的字节码,那么这样的话就成了一组同步函数。
下面的例子有两组同步函数头两个线程对 print() 进行同步互斥,后两个线程对 printName() 进行同步互斥;也就是他们两组是各干各的,互不影响的。
public synchronized static void print() {
//synchronized (ThreadGroup.class) {
String source = "我是中国人";
char[] cs = source.toCharArray();
System.out.println(Thread.currentThread().getName());
for (int j = 0; j < 30; j++) {
System.out.println(j + " -----------------> ");
for (int i = 0; i < cs.length; i++) {
System.out.print(cs[i]);
}
System.out.println();
}
//}
}
public synchronized static void printName() {
//synchronized (String.class) {
System.out.println(Thread.currentThread().getName());
String source = "你好吗";
char[] cs = source.toCharArray();
for (int j = 0; j < 30; j++) {
System.out.println(j+" -----------------> ");
for (int i = 0; i < cs.length; i++) {
System.out.print(cs[i]);
}
System.out.println();
}
//}
}
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
print();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
print();
}
}).start();
//--------------------------第二组
new Thread(new Runnable() {
@Override
public void run() {
printName();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
printName();
}
}).start();
}
因为 print() 和 printName() 都是 static 的,而且又有 synchronized 关键字修饰.所以同步监视器对象都是当前类的字节码对象。
所以实际上以上只有一组同步函数,而不是两组。
从输出结果可以看出,当一个线程执行了 print() 或 printName() 方法,其他 3 个线程只有等该线程执行完毕才能接着执行。
如果多组的话,一个组的同步互斥不会影响其他组的执行.
由于输出结果较多就不粘贴了.
把 print() 和 printName() 两个方法改成一下就是两组同步了。
public static void print() {
synchronized (ThreadGroup.class) {
String source = "我是中国人";
char[] cs = source.toCharArray();
System.out.println(Thread.currentThread().getName());
for (int j = 0; j < 30; j++) {
System.out.println(j + " -----------------> ");
for (int i = 0; i < cs.length; i++) {
System.out.print(cs[i]);
}
System.out.println();
}
}
}
public static void printName() {
synchronized (String.class) {
System.out.println(Thread.currentThread().getName());
String source = "你好吗";
char[] cs = source.toCharArray();
for (int j = 0; j < 30; j++) {
System.out.println(j+" -----------------> ");
for (int i = 0; i < cs.length; i++) {
System.out.print(cs[i]);
}
System.out.println();
}
}
}
从输出结果可以看出,两组同步是互相交替执行的。