1

我有一个静态函数,例如:

public static void foo()
{
    //code follows
    System.out.println(Thread.currentThread().getName());
    //code follows
}

并且多个线程同时调用此函数。我已经使用

Thread.setName(String)

当我执行代码时,打印语句将只打印一个线程的名称。如何识别当前执行 foo() 函数的所有线程的名称?

编辑:

public class FooThread extends Thread
{
public FooThread(String name)
{
this.setName(name);
}
@Override public void run()
{
//do something
//do something
Main.foo();

}
}


//Main Class
public class Main
{
public static void main(String[] args)
{
for(int i=0;i<6;++i)
{
new FooThread("Thread"+i).start();
}
}

public static void foo()
{
//do something 
while(true)
{
//do something
System.out.println(Thread.currentThread().getName());
}

}
}
4

4 回答 4

4

您已经显示了调用您的代码的线程的名称。证明这一点的代码:

public class Foo2 {
   public static synchronized void foo() {
      System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
      int maxCount = 10;
      for (int i = 0; i < maxCount; i++) {
         Thread thread = new Thread(new Runnable() {
            public void run() {
               foo();
            }
         });
         thread.setName("Thread " + i);
         thread.start();
         long sleepTime = 1000;;
         try {
            Thread.sleep(sleepTime);
         } catch (InterruptedException e) {}
      }
   }
}

返回:

Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
Thread 7
Thread 8
Thread 9

您的问题在于未显示的代码。

  • 要么你的方法被一个且只有一个线程调用,要么
  • 或者你给你的所有线程都赋予了相同的名称。

同样,对于您当前设置的实际问题的完整解决方案,请创建并发布类似于我在上面发布的内容的sscce 。据我们所知,您可能会调用run()您的线程,并且在我们看到并重现您的问题之前,我认为我们无法完全理解它。


编辑
关于您的 SSCCE:比较以下两种方法的结果 foo1() 和 foo2()

class FooThread extends Thread {

   public FooThread(String name) {
      this.setName(name);
   }

   @Override
   public void run() {
      // do something
      // do something

      Main.foo1();  // !! Swap comments
      // Main.foo2(); // !! Swap comments
   }
}

// Main Class
public class Main {
   private static final long SLEEP_TIME = 4;

   public static void main(String[] args) {
      for (int i = 0; i < 6; ++i) {
         new FooThread("Thread" + i).start();
      }
   }

   public static void foo1() {
      // do something
      while (true) {
         // do something
         synchronized (Main.class) {
            System.out.println(Thread.currentThread().getName());
         }
         try {
            Thread.sleep(SLEEP_TIME);
         } catch (InterruptedException e) {}

      }
   }

   public static void foo2() {
      while (true) {
         System.out.println(Thread.currentThread().getName());
      }
   }
}

如果您的 while 循环不是那么紧,而是通过一个短的 Thread.sleep 产生 CPU,您会看到更多不同的线程在更接近的地方共享 foo。

但同样,您的代码也证明您的线程名称 * are8正在显示,但您可能只看到一个名称,因为该线程正在占用 CPU。

于 2013-09-22T21:11:23.743 回答
1

另一种选择是获取所有线程堆栈并在其中查找所有线程foo() 这具有没有开销或额外代码的好处,除了捕获您想要的信息。

顺便说一句:你能否更清楚地说明为什么需要这些信息,因为我怀疑有更好的方法来做你真正想做的事情?

于 2013-09-22T21:13:09.510 回答
0

如果您只想获取线程数,请使用线程安全计数器来存储线程数。当 foo() 开始时增加计数器,当 foo() 退出时减少计数器。

如果您需要获取名称,请使用哈希集(如果存在重复的线程名称,则使用列表)来存储名称:在 foo() 开始时添加名称,并在 foo() 退出时删除名称。确保对哈希集的访问是线程安全的。您还需要另一种方法来打印散列集的内容,因此您可以随时调用它来查看执行 foo() 的线程的名称是什么。

于 2013-09-22T21:06:16.723 回答
0

您可以在方法开始时(在同步块中)将该名称放入列表中,并在最后再次将其删除。

List allTheNames = Collections.synchronizedList(new ArrayList<String>());

public void foo() {
    allTheNames.add(Thread.currentThread().getName());
    // now allTheNames contains all the names of all threads currently in this method.
    System.out.println(allTheNames.toString());
    allTheNames.remove(Thread.currentThread().getName());
}

当然,如果您同时更改线程的名称,那将无法正常工作,但是您为什么要这样做呢?

Thread如果您需要名称的其他信息,您也可以存储它本身。

于 2013-09-22T21:07:24.950 回答