在线程启动之前获取线程的ThreadID

时间:2013-05-11 02:48:24

标签: java multithreading

我有这个配对机制的想法,通过他们的ThreadID识别客户端。当线程被销毁时,客户端的配对被破坏,其ID被设置为-1。

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

我想知道我是否可以创建一个线程,获取ID,然后稍后在OR上设置runnable,如果我可以获取正在运行我的函数的当前线程的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..
            }
        }
    });
}

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

2 个答案:

答案 0 :(得分:3)

线程id是不可变的,因此当线程终止时,您将无法将其设置为-1。

创建线程后立即创建id,线程一启动就 not ,因此您可以创建线程,读取其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 :(得分:1)

稍后运行runnable:

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();
        }
    }
}

我使用了信号量。你只需要某种锁定或条件。当线程启动时,它会尝试获取锁定,导致它等待"等待"直到它可以获得它。当您在稍后的某个时间点设置runnable时,它将释放锁定,导致线程获取它,释放它并继续执行。