服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java中的线程组


  所有线程都隶属于一个线程组。那可以是一个默认线程组,亦可是一个创建线程时明确指定的组。在创建之初,线程被限制到一个组里,而且不能改变到一个不同的组。每个应用都至少有一个线程从属于系统线程组。若创建多个线程而不指定一个组,它们就会自动归属于系统线程组。
  线程组也必须从属于其他线程组。必须在构建器里指定新线程组从属于哪个线程组。若在创建一个线程组的时候没有指定它的归属,则同样会自动成为系统线程组的一名属下。因此,一个应用程序中的所有线程组最终都会将系统线程组作为自己的“父”。
  之所以要提出“线程组”的概念,很难从字面上找到原因。这多少为我们讨论的主题带来了一些混乱。一般地说,我们认为是由于“安全”或者“保密”方面的理由才使用线程组的。根据arnold和gosling的说法:“线程组中的线程可以修改组内的其他线程,包括那些位于分层结构最深处的。一个线程不能修改位于自己所在组或者下属组之外的任何线程”(注释①)。然而,我们很难判断“修改”在这儿的具体含义是什么。下面这个例子展示了位于一个“叶子组”内的线程能修改它所在线程组树的所有线程的优先级,同时还能为这个“树”内的所有线程都调用一个方法。
  ①:《the java programming language》第179页。该书由arnold和jams gosling编著,addison-wesley于1996年出版
  //: testaccess.java
  // 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()");
   }
  }
  class testthread2 extends testthread1 {
   testthread2(threadgroup g, string name) {
   super(g, name);
   start();
   }
   public void run() {
   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();
   }
  } ///:~
  在main()中,我们创建了几个threadgroup(线程组),每个都位于不同的“叶”上:x没有参数,只有它的名字(一个string),所以会自动进入“system”(系统)线程组;y位于x下方,而z位于y下方。注意初始化是按照文字顺序进行的,所以代码合法。
  有两个线程创建之后进入了不同的线程组。其中,testthread1没有一个run()方法,但有一个f(),用于通知线程以及打印出一些东西,以便我们知道它已被调用。而testthread2属于testthread1的一个子类,它的run()非常详尽,要做许多事情。首先,它获得当前线程所在的线程组,然后利用getparent()在继承树中向上移动两级(这样做是有道理的,因为我想把testthread2在分级结构中向下移动两级)。随后,我们调用方法activecount(),查询这个线程组以及所有子线程组内有多少个线程,从而创建由指向thread的句柄构成的一个数组。enumerate()方法将指向所有这些线程的句柄置入数组gall里。然后在整个数组里遍历,为每个线程都调用f()方法,同时修改优先级。这样一来,位于一个“叶子”线程组里的线程就修改了位于父线程组的线程。
  调试方法list()打印出与一个线程组有关的所有信息,把它们作为标准输出。在我们对线程组的行为进行调查的时候,这样做是相当有好处的。下面是程序的输出:
  java.lang.threadgroup[name=x,maxpri=10]
   thread[one,5,x]
   java.lang.threadgroup[name=y,maxpri=10]
   java.lang.threadgroup[name=z,maxpri=10]
   thread[two,5,z]
  one f()
  two f()
  java.lang.threadgroup[name=x,maxpri=10]
   thread[one,1,x]
   java.lang.threadgroup[name=y,maxpri=10]
   java.lang.threadgroup[name=z,maxpri=10]
   thread[two,1,z]
  list()不仅打印出threadgroup或者thread的类名,也打印出了线程组的名字以及它的最高优先级。对于线程,则打印出它们的名字,并接上线程优先级以及所属的线程组。注意list()会对线程和线程组进行缩排处理,指出它们是未缩排的线程组的“子”。
  大家可看到f()是由testthread2的run()方法调用的,所以很明显,组内的所有线程都是相当脆弱的。然而,我们只能访问那些从自己的system线程组树分支出来的线程,而且或许这就是所谓“安全”的意思。我们不能访问其他任何人的系统线程树。
  线程组的控制
  抛开安全问题不谈,线程组最有用的一个地方就是控制:只需用单个命令即可完成对整个线程组的操作。下面这个例子演示了这一点,并对线程组内优先级的限制进行了说明。括号内的注释数字便于大家比较输出结果:
  //: threadgroup1.java
  // how thread groups control priorities
  // of the threads inside them.
  public class threadgroup1 {
   public static void main(string[] args) {
   // get the system thread & print its info:
   threadgroup sys =
   thread.currentthread().getthreadgroup();
   sys.list(); // (1)
   // reduce the system thread group priority:
   sys.setmaxpriority(thread.max_priority - 1);
   // increase the main thread priority:
   thread curr = thread.currentthread();
   curr.setpriority(curr.getpriority() + 1);
   sys.list(); // (2)
   // attempt to set a new group to the max:
   threadgroup g1 = new threadgroup("g1");
   g1.setmaxpriority(thread.max_priority);
   // attempt to set a new thread to the max:
   thread t = new thread(g1, "a");
   t.setpriority(thread.max_priority);
   g1.list(); // (3)
   // reduce g1's max priority, then attempt
   // to increase it:
   g1.setmaxpriority(thread.max_priority - 2);
   g1.setmaxpriority(thread.max_priority);
   g1.list(); // (4)
   // attempt to set a new thread to the max:
   t = new thread(g1, "b");
   t.setpriority(thread.max_priority);
   g1.list(); // (5)
   // lower the max priority below the default
   // thread priority:
   g1.setmaxpriority(thread.min_priority + 2);
   // look at a new thread's priority before
   // and after changing it:
   t = new thread(g1, "c");
   g1.list(); // (6)
   t.setpriority(t.getpriority() -1);
   g1.list(); // (7)
   // make g2 a child threadgroup of g1 and
   // try to increase its priority:
   threadgroup g2 = new threadgroup(g1, "g2");
   g2.list(); // (8)
   g2.setmaxpriority(thread.max_priority);
   g2.list(); // (9)
   // add a bunch of new threads to g2:
   for (int i = 0; i < 5; i++)
   new thread(g2, integer.tostring(i));
   // show information about all threadgroups
   // and threads:
   sys.list(); // (10)
   system.out.println("starting all threads:");
   thread[] all = new thread[sys.activecount()];
   sys.enumerate(all);
   for(int i = 0; i < all.length; i++)
   if(!all[i].isalive())
   all[i].start();
   // suspends & stops all threads in
   // this group and its subgroups:
   system.out.println("all threads started");
   sys.suspend(); // deprecated in java 1.2
   // never gets here...
   system.out.println("all threads suspended");
   sys.stop(); // deprecated in java 1.2
   system.out.println("all threads stopped");
   }
  } ///:~
  下面的输出结果已进行了适当的编辑,以便用一页能够装下(java.lang.已被删去),而且添加了适当的数字,与前面程序列表中括号里的数字对应:
  (1) threadgroup[name=system,maxpri=10]
   thread[main,5,system]
  (2) threadgroup[name=system,maxpri=9]
   thread[main,6,system]
  (3) threadgroup[name=g1,maxpri=9]
   thread[a,9,g1]
  (4) threadgroup[name=g1,maxpri=

扫描关注微信公众号