一、线程组合线程池的异同:
线程组:
线程组存在的意义,首要原因是安全。
java默认创建的线程都是属于系统线程组,而同一个线程组的线程是可以相互修改对方的数据的。
但如果在不同的线程组中,那么就不能“跨线程组”修改数据,可以从一定程度上保证数据安全。
线程池:
线程池存在的意义,首要作用是效率。
线程的创建和结束都需要耗费一定的系统时间(特别是创建),不停创建和删除线程会浪费大量的时间。所以,在创建出一条线程并使其在执行完任务后不结束,而是使其进入休眠状态,在需要用时再唤醒,那么 就可以节省一定的时间。
如果这样的线程比较多,那么就可以使用线程池来进行管理。保证效率。
线程组和线程池共有的特点:
1,都是管理一定数量的线程
2,都可以对线程进行控制---包括休眠,唤醒,结束,创建,中断(暂停)--但并不一定包含全部这些操作。
二、总结:
在Java中每个线程都属于某个线程组(ThreadGroup)。例如,如果在main()中产生一个线程,则这个线程属于main线程组管理的一员,您可以使用下面的指令来获得目前线程所属的线程组名称:
Thread.currentThread().getThreadGroup().getName(); |
一个线程产生时,都会被归入某个线程组,视线程是在哪个线程组中产生而定。如果没有指定,则归入产生该子线程的线程组中。您也可以自行指定线程组,线程一旦归入某个组,就无法更换组。 java.lang.ThreadGroup类正如其名,可以统一管理整个线程组中的线程,您可以使用以下方式来产生线程组,而且一并指定其线程组:
ThreadGroup threadGroup1 = new ThreadGroup("group1"); |
ThreadGroup中的某些方法,可以对所有的线程产生作用,例如interrupt()方法可以interrupt线程组中所有的线 程,setMaxPriority()方法可以设置线程组中线程所能拥有的最高优先权(本来就拥有更高优先权的线程不受影响)。
如果想要一次获得线程组中所有的线程来进行某种操作,可以使用enumerate()方法,例如:
Thread[] threads = new Thread[threadGroup1.activeCount()]; |
ThreadGroup中有一个uncaughtException()方法。当线程组中某个线程发生Unchecked exception异常时,由执行环境调用此方法进行相关处理,如果有必要,可以重新定义此方法,请看下面的示例。
package onlyfun.caterpillar;
public class ThreadGroupDemo { public static void main(String[] args) { ThreadGroup threadGroup1 = // 这是匿名类写法 new ThreadGroup("group1") { // 继承ThreadGroup并重新定义以下方法 // 在线程成员抛出unchecked exception // 会执行此方法 public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName() + ": " + e.getMessage()); } };
// 这是匿名类写法 Thread thread1 = // 这个线程是threadGroup1的一员 new Thread(threadGroup1, new Runnable() { public void run() { // 抛出unchecked异常 throw new RuntimeException("测试异常"); } });
thread1.start(); } } |
在uncaughtException()方法的参数中,第一个参数可以获得发生异常的线程实例,而第二个参数可以获得异常对象,范例中显示了线程的名称及异常信息。
三、附上示例代码:public class TestThreadGroup {
static class MyThread extends Thread {
@Override
public void run() {
ThreadGroup currentThreadGroup = Thread.currentThread()
.getThreadGroup();
System.out.println(currentThreadGroup.getName() + ","
+ currentThreadGroup.getParent().getName());
System.out.println(getName() + "," + getId() + ","
+ Thread.currentThread().getName());
System.out.println(Thread.currentThread().getState());
// if(Thread.currentThread().getState()==Thread.State.RUNNABLE)
{
}
// super.run();
}
}
public static void main(String[] args) throws Exception {
new MyThread().start();
// ThreadGroup currentThreadGroup=Thread.currentThread().getThreadGroup();
// System.out.println(currentThreadGroup.getName()+","+currentThreadGroup.getParent().getName());
test001();
ThreadGroup sys = Thread.currentThread().getThreadGroup().getParent();
// sys.list(); // (1)
// System.out.println(JSON.toJSONString(sys));
//test002();
}
private static void test002() throws InterruptedException {
// 创建线程组对象。
ThreadGroup tg = new ThreadGroup("group 1");
// 向线程组中加入10个线程。
for (int i = 0; i < 10; i++) {
Thread th = new Thread(tg, new TestRunnable(), "thread_" + i);
th.start();
}
// 等待2秒。
Thread.sleep(2000);
// 中断所有线程。
tg.interrupt();
// 输出
System.out.println(tg.activeCount());
}
private static class TestRunnable implements Runnable {
@Override
public void run() {
String thName = Thread.currentThread().getName();
System.out.printf("'%s' started. \n", thName);
while (!Thread.currentThread().isInterrupted()) {
}
System.out.printf("'%s' ended. \n", thName);
}
}
// 通过ThreadGroup管理线程
private static void test001() {
// ThreadGroup group=new ThreadGroup("group");
// Thread thread=new Thread(group,"the first thread of group");
// 这是匿名类写法
ThreadGroup threadGroup1 = new ThreadGroup("group1") {
// 继承ThreadGroup并重新定义以下方法
// 在线程成员抛出unchecked exception
// 会执行此方法
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + ": " + e.getMessage());
}
};
// 这是匿名类写法 // 这个线程是threadGroup1的一员
Thread thread1 = new Thread(threadGroup1, new Runnable() {
public void run() {
// 抛出unchecked异常
throw new RuntimeException("测试异常 fuck");
}
});
thread1.start();
}
}
// How threads can access other threads in a parent thread group
public class TestAccess {
public static void main(String[] args) {
ThreadGroup x = new ThreadGroup("x"),
y = new ThreadGroup(x, "y"),
z = new ThreadGroup(y, "z");
Thread one = new TestThread1(x, "one"),
two = new TestThread2(z, "two");
}
}
class TestThread1 extends Thread {
private int i;
TestThread1(ThreadGroup g, String name) {
super(g, name);
}
void f() {
i++; // modify this thread
System.out.println(getName() + " f()");
}
}
//继承线程1
class TestThread2 extends TestThread1 {
TestThread2(ThreadGroup g, String name) {
super(g, name);
start();
}
public void run() {
//使用ThreadGroup 父线程可以控制子线程
ThreadGroup g = getThreadGroup().getParent().getParent();
//打印线程组信息
g.list();
Thread[] gAll = new Thread[g.activeCount()];//活动子线程数量
//获取活动的子线程
g.enumerate(gAll);
for (int i = 0; i < gAll.length; i++) {
gAll[i].setPriority(Thread.MIN_PRIORITY);
((TestThread1) gAll[i]).f();
}
//打印线程组信息
g.list();
}
}