如何“完全”同时启动两个线程

2022-08-31 10:01:52

线程应在同一瞬间启动。我知道,如果你这样做,在下一次执行之前需要几毫秒。thread1.start()thread2.start()

这是可能的还是不可能的?


答案 1

要在完全相同的时间启动线程(至少尽可能好),您可以使用循环管理器

// We want to start just 2 threads at the same time, but let's control that 
// timing from the main thread. That's why we have 3 "parties" instead of 2.
final CyclicBarrier gate = new CyclicBarrier(3);

Thread t1 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};
Thread t2 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};

t1.start();
t2.start();

// At this point, t1 and t2 are blocking on the gate. 
// Since we gave "3" as the argument, gate is not opened yet.
// Now if we block on the gate from the main thread, it will open
// and all threads will start to do stuff!

gate.await();
System.out.println("all threads started");

这不一定是 ,您也可以使用锁甚至锁。CyclicBarrierCountDownLatch

这仍然无法确保它们在标准JVM上完全同时启动,但您可以非常接近。例如,当您进行性能测试时,非常接近仍然很有用。例如,如果您尝试测量具有不同线程数的数据结构的吞吐量,则需要使用这种构造来获得最准确的结果。

在其他平台上,确切地说,启动线程可能是一个非常有效的要求。


答案 2

您可以使用CountDownLatch来实现此目的。请在下面找到一个示例。虽然 t1 和 t2 已启动,但这些线程会一直等待,直到主线程倒计时闩锁。构造函数中提到了所需的倒计时数。倒计时闩锁也可用于等待线程完成执行,以便主线程可以进一步进行(相反的情况)。这个类从Java 1.5开始就被包括在内。

import java.util.concurrent.CountDownLatch;


public class ThreadExample
{
    public static void main(String[] args) 
    {
        CountDownLatch latch = new CountDownLatch(1);
        MyThread t1 = new MyThread(latch);
        MyThread t2 = new MyThread(latch);
        new Thread(t1).start();
        new Thread(t2).start();
        //Do whatever you want
        latch.countDown();          //This will inform all the threads to start
        //Continue to do whatever
    }
}

class MyThread implements Runnable
{
    CountDownLatch latch;
    public MyThread(CountDownLatch latch) 
    {
        this.latch = latch;
    }
    @Override
    public void run() 
    {
        try 
        {
            latch.await();          //The thread keeps waiting till it is informed
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Do the actual thing
    }
}