2013-05-11 137 views
1

我有这种通过线程标识客户端的配对机制。当线程被销毁时,客户端的配对被销毁并且其ID被设置为-1。在线程开始之前获取线程的线程ID

现在为了让我获得线程ID,线程当然必须运行或启动。

我想知道如果我可以创建一个线程,获得ID,然后设置可运行后,或者如果我能得到的是正在运行我的函数当前线程的ID ..

例子就是我想做的事:

void createClientThreaded(final Client client) { 
    new Thread(new Runnable() { 
     @Override public void run() { 
      while(!client.stop()) { 
       Utils.sleep(1000); 
       //Do other stuff here.. 

       client.setThreadID(/* This Thread's ID */); 

       // Do other stuff here.. 
      } 
     } 
    }); 
} 

有关我如何做到这一点的任何想法?线程标识符在每个进程中是唯一的,还是整个系统都是唯一的?换句话说,可以同时运行两个jar文件具有相同的线程ID?

+0

呃我不确定我是否做得对,但我做到了:Thread.currentThread()。getID();这似乎工作。但是,无法确定每个进程或系统是否是唯一的。 – Brandon 2013-05-11 03:11:15

+0

这个问题和答案不包括如何“稍后设置线程可运行” – 2017-09-05 12:22:22

+0

@MakanTayebi但它涵盖了我设置线程ID时的需要。您可以使用条件变量或锁定延迟线程,并稍后设置可运行。我可以展示如果你喜欢(我会发布一个解决方案)。当我发布这篇文章时,我对Java并不擅长,只是想要一种方法来稍后设置runnable或获取尚未启动的线程的threadID。 – Brandon 2017-09-05 12:25:45

回答

3

线程ID是不可变的,所以当线程终止时你不能将它设置为-1。

一旦创建线程,就创建id,不是,因此只要线程启动,就可以创建线程,读取其id并稍后启动它。

但是,如果您正在创建并销毁大量线程,那么您将产生较高的运行时成本。使用ThreadPoolExecutor来执行你的runnable会更有效率,但是这样会排除创建线程,读取它的id和稍后启动线程的选项。另一种选择是创建自己的类,该类使用可变ID实现Runnable。

class MyRunnable implements Runnable { 
    private static AtomicLong idCounter = new AtomicLong(0); 
    private long id; 

    public MyRunnable() { this.id = idCounter.getAndIncrement(); } 

    public void setId(long id) { this.id = id; } 
    public long getId() { return this.id; } 
    public void run() {} 
} 

线程ID是每个进程,而不是系统范围的。另外,该过程可以重用线程id(例如,如果id = 5的线程终止,则过程可以将id = 5分配给新线程)。

1

要在一段时间后运行一个可运行的:

import java.util.concurrent.Semaphore; 

public class Main { 
    public static void main(String[] args) { 
     DelayedExecutionThread blocker = new DelayedExecutionThread(); 
     Thread t = blocker.getThread(); 
     t.start(); 

     System.out.println("Thread Started.."); 
     sleep(3000); 
     System.out.println("Executing.."); 

     blocker.setRunnable(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("RAN THE THREAD LATER"); 
      } 
     }); 

     sleep(1); 
     System.out.println("Executed.."); 
    } 

    private static class DelayedExecutionThread { 
     private Semaphore lock = new Semaphore(1, true); 
     private Thread thread; 
     private Runnable target; 

     public DelayedExecutionThread() { 
      this.lock.acquireUninterruptibly(); 

      this.thread = new Thread(new Runnable() { 
       @Override 
       public void run() { 
        DelayedExecutionThread.this.lock.acquireUninterruptibly(); 
        DelayedExecutionThread.this.lock.release(); 
        DelayedExecutionThread.this.lock = null; 

        if (DelayedExecutionThread.this.target != null) { 
         DelayedExecutionThread.this.target.run(); 
        } 
       } 
      }); 
     } 

     public Thread getThread() { 
      return this.thread; 
     } 

     public void setRunnable(Runnable runnable) { 
      this.lock.release(); 
      this.target = runnable; 
     } 
    } 

    private static void sleep(long millis) { 
     try { 
      Thread.sleep(millis); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

我用了一个信号。你只需要某种锁定或条件。当线程启动时,它会尝试获取导致它“等待”的锁,直到它可以获取它为止。当您稍后设置可运行时,它将释放导致线程获取它的锁,释放它并继续执行。