1

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

现在,为了让我获得线程 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..
            }
        }
    });
}

关于如何做到这一点的任何想法?线程 ID 是每个进程唯一的还是整个系统唯一的?也就是说,两个同时运行的jar文件可以有相同的Thread ID吗?

4

2 回答 2

3

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

id是线程一创建就创建的,不是线程一启动就创建的,所以你可以创建线程,读取它的id,稍后再启动。

但是,如果您要创建和销毁大量线程,那么您将产生高昂的运行时成本。使用ThreadPoolExecutor来执行您的可运行文件会更有效,但是这排除了创建线程、读取其 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分配给新线程)。

于 2013-05-11T03:11:48.467 回答
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();
        }
    }
}

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

于 2017-09-05T13:14:07.640 回答