JAVA 多线程实现(三)

2014-11-24 03:24:28 · 作者: · 浏览: 5
c void main(String[] args) {
MainRun mr = new MainRun();
T1 t1 = new T1(mr);
T2 t2 = new T2(mr);
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t2);
th1.start();
th2.start();
}

}

class T1 implements Runnable{

MainRun mr = null;
T1(MainRun mr){
this.mr = mr;
}
@Override
public void run() {
while(true){
mr.countI();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class T2 implements Runnable{
MainRun mr = null;
T2(MainRun mr){
this.mr = mr;
}
@Override
public void run() {
while(true){
mr.countI();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上面这段代码相当于将countI方法做成同步方法。

同步容器操作
某些Java容器类天生就是线程安全的,比如Vector和HashTable但是,我们知道
同步方法需要申请和释放对象锁,开销比较大。因此对于某些只有一个线程访问的情况
使用Vector或者HashTable是不效率的。

因此Java的设计者想到了一个方法,就是Java2的新增容器一般都不是线程安全的。
即add remove等方法都不是同步的。
为了应对多线程的情况,必须使用Collection类的包装方法,将其包装成为同步方法。
被包装的容器的所有的方法将变成线程安全的。同时,Java代码应当避免再对包装
之前的容器进行直接的引用。

public static Collection synchronizedCollection(Collection c)

public static List synchronizedList(List l)

public static Map synchronizedMap(Map m)

public static Set synchronizedSet(Set s)

public static SortedMap synchronizedSortedMap(SortedMap sm)

public static SortedSet synchronizedSortedSet(SortedSet ss)

经过包装之后,就是线程安全的了。

当然,如果不想包装,那么就需要使用synchronized同步块进行控制
比如
List wordList = new ArrayList();
synchronized(wordList){
//something you want to do
}

特别的是,当用到迭代器的时候,因为迭代器不能被包装,而使用的时候又不能被其他的线程
随意增加或者删除元素。所以必须使用这种同步块的方法。

避免死锁
再重复一遍,使用synchronized关键字来修饰一个实例方法,相当于声明为这个对象上了一个对象级别的锁
和使用synchronized(object)的道理是一个样子的。

发生死锁的一个经典的例子
package cn.bj.brook.test;

public class MainRun {

/**
* @param args
*/
int i = 0;
int m = 0;

public void countI(){
System.out.println(Thread.currentThread().getName()+" is Entering the countI method");
synchronized(this){
i=i+1;
String strName = Thread.currentThread().getName();
System.out.println("In "+strName+" i="+i);
countM();
}
System.out.println(Thread.currentThread().getName()+" is Leaving the countI method");
}

public void countM(){
System.out.println(Thread.currentThread().getName()+" is Entering the countM method");
try {
System.out.println(Thread.currentThread().getName()+" is sleeping");
Thread.sleep(10000);
} catch (InterruptedException e) {
}
synchronized(this){
m=m+1;
String strName = Thread.currentThread().getName();
System.out.println("In "+strName+" m="+m);
}
System.out.println(Thread.currentThread().getName()+" is Leaving the countM method");
}

public static void main(String[] args) {
MainRun mr = new MainRun();
DeadLock m1 = new DeadLock();
DeadLock m2 = new DeadLock();
T1 t1 = new T1(m1,m2);
T2 t2 = new T2(m1,m2);
Thread th1 = new Thread(t1,"ThreadA");
Thread th2 = new Thread(t2,"ThreadB");
th1.start();
th2.start();
}

}

class DeadLock{

//这个方法的关键字相当于给DeadLock对象上锁
public syn