1.线程群组(ThreadGroup)
在官方API对ThreadGroup有如下解释:
线程组表示一个线程的集合。此外,线程组也可以包含其他线程组。线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组。 允许线程访问有关自己的线程组的信息,但是不允许它访问有关其线程组的父线程组或其他任何线程组的信息。
类名是:java.lang.ThreadGroup
产生管理群主线程方法如下:
ThreadGroup threadgroup1=new ThreadGroup("group1");//产生群组
Thread thread1=new Thread(threadgroup1,"group1's member");//thread1在线程组group1中
ThreadGroup中的部分方法:
interrupt()可以中断群组中的所有线程
setMaxPriority()可以设定群组中所有线程最大优先权
enumerate() 把对此线程组中的所有活动子组的引用复制到指定数组中。
activeCount() 返回此线程组中活动线程的估计数。
uncaughtException(Thread t, Throwable e) //当此线程组中的线程因为一个未捕获的异常而停止,并且线程没有安装特定Thread.UncaughtExceptionHandler 时,由 JVM 调用此方法。
2.synchronized和volatile
如下示例:
import java.util.ArrayList;
public class ArrayListSyn{
public static void main(String [] args){
final ArrayList list =new ArrayList();
Thread t1=new Thread(){
public void run(){
while(true){
list.add(1);
}
}
};
Thread t2=new Thread(){
public void run(){
while(true){
list.add(2);
}
}
};
t1.start();
t2.start();
}
}
结果:
2.1. synchronized
synchronized 是同步的意思,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized 修饰的方法 或者 代码块。
在线程存取同一对象相同资源所引发的竞速情况(Race condition),会引发如上图ArrayIndexOutOfBoundsException异常的情况,可以使用在方法前加上synchronized关键字如:
...
public synchronized void add(Object o){
if(next ==list.length){
list=Arrays.copyOf(list,list.length*2);
}
list[next++]=o;
}
....
这是因为每个对象都有个内部锁定,或称为监控锁定,被标志为synchronized的区块将会被监控,任何线程都要执行synchronized区块都必须先取得指定对象的指定。如果A线程已取得对象锁定开始执行synchronized区块,B线程也想执行synchronized区块,会因无法取得对象锁定而进入等待锁定状态,直到A线程释放锁定。B线程才有机会取得锁定二执行synchronized区块。
当然不正确的使用synchronized有可能造成效能低下,另一个问题则是死结(Dead lock)。例如,有些资源在多线程下彼此交叉取用,就有可能造成死结。
实例:
class Resource{
private String name;
private int resource;
Resource(String name,int resource){
this.name=name;
this.resource=resource;
}
String getName(){
return name;
}
synchronized int doSome(){
return ++resource;
}
synchronized void cooperate(Resource resource){
resource.doSome();
System.out.printf("%s整合 %s的资源%n",this.name,resource.getName());
}
}
public class SynDeadLock{
public static void main(String [] args){
final Resource resource1=new Resource("resource1",20);
final Resource resource2=new Resource("resource2",30);
Thread t1=new Thread(){
public void run(){
for(int i=0;i<10;i++){
resource1.cooperate(resource2);
}
}
};
Thread t2=new Thread(){
public void run(){
for(int i=0;i<10;i++){
resource2.cooperate(resource1);
}
}
};
t1.start();
t2.start();
}
}
结果:
程序死在如图位置,这是因为发生了死结。因为,t1在调用 resource1.cooperate(resource2);时,会取得resource1的锁定,若此时t2调用 resource2.cooperate(resource1);时,会取得resource2的锁定,而t1要用传入的resource2调用doSome(),理应取得resource2的锁定,但锁定被t2拿走了,于是t1进入等待,同理t2也进入等待,那么二者互不让步的状态则叫做死结。
2.2. volatile
变量上声明volatile 表示变量是不稳定的、易变得,也就是可能在多线程下存取,这保证变量的可见性,也就是若有线程变动了变量值,另一线程也可以看到变更。被volatile标识的变量,变量值的存取一定是在共享内存中进行。