6

如何启动两个线程,其中 thread1 首先执行,thread2 在 thread1 结束时启动,而 main 方法线程可以继续其工作而不锁定其他两个?

我试过 join() 但是它需要从必须等待另一个的线程调用,没有办法做像 thread2.join(thread1); 这样的事情 如果我在 main() 中调用连接,我将有效地停止主线程的执行,而不仅仅是线程 2。

因此,我尝试使用 ExecutorService 但同样的问题。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Test
{
    public static void main(String args[]) throws InterruptedException
    {
        System.out.println(Thread.currentThread().getName() + " is Started");

        class TestThread extends Thread
        {
            String name;
            public TestThread(String name)
            {
                this.name = name;
            }

            @Override
            public void run()
            {
                try
                {
                    System.out.println(this + " is Started");
                    Thread.sleep(2000);
                    System.out.println(this + " is Completed");
                }
                catch (InterruptedException ex)  {  ex.printStackTrace(); }
            }

            @Override
            public String toString()  { return "Thread " + name; }
        }

        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(new TestThread("1"));

        boolean finished = executor.awaitTermination(1, TimeUnit.HOURS);

        if(finished)
        {
           //I should execute thread 2 only after thread 1 has finished
            executor.execute(new TestThread("2"));
        }

        //I should arrive here while process 1 and 2 go on with their execution
        System.out.println("Hello");
    }
}

#EDIT:为什么我需要这个:

我需要这个,因为 Thread1 将元素从数据库表复制到另一个数据库,thread2 必须复制一个链接表,该表引用从 thread1 复制的表。因此,只有在 thread1 完成后,thread2 才必须开始填充其链接表,否则数据库会给出完整性错误。现在想象一下,由于复杂的链接表,我有几个具有不同优先级的线程,你有一个想法。

4

8 回答 8

4

第二个线程可以像这样自定义(将前一个线程作为参数):

public static void main(String[] a) {
    Thread first = new Thread(new Runnable() {
        @Override
        public void run() {

        }
    });

    Thread second = new MyThread(first);
    first.start();
    second.start();

    //continue executing
}

public static class MyThread extends Thread {

    private Thread predecessor;

    public MyThread(Thread predecessor) {
        this.predecessor = predecessor;
    }

    public void run() {
        if (predecessor != null && predecessor.isAlive()) {
            try {
                predecessor.join();
            } catch (InterruptedException e) {}
        }
        //do your stuff
    }
}
于 2013-07-04T14:24:05.620 回答
3

我很确定你有什么问题,因为这必须有效并且确实有效:

new Thread() {
    @Override
    public void run() {
        TestThread t1= new TestThread("1");
        TestThread t2= new TestThread("2");
        try {
            t1.start();
            t1.join();
            t2.start();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}.start();

输出是:

main is Started
Hello
Thread 1 is Started
Thread 1 is Completed
Thread 2 is Started
Thread 2 is Completed

另一种选择是扩展“线程 1”的 TestThread 以在“线程 2”完成自己的工作后执行它的工作。与此类似的东西:

final TestThread t2= new TestThread("2");
TestThread t1= new TestThread("1") {
    @Override
    public void run() {
        super.run(); //finish t1 work
        t2.start();  // start t2 work
    }
};
t1.start();
于 2013-07-04T14:19:07.997 回答
3

您可以使用CountDownLatch

在主线程中创建它,将其传递给两个线程,并在线程一退出时对其调用倒计时,并在线程2开始时等待它倒计时。

于 2013-07-04T14:24:23.497 回答
1

为什么不让 thread1 成为启动 thread2 的那个?

// in main
new Thread(new Runnable() {
    @Override public void run() {
        // do thread1 work
        new Thread(new Runnable() {
              @Override public void run() { /* do thread2 work */ }
        }).start();
    }
}).start();

但是,与让 thread1 做 100% 的后台工作相比,为什么要这样做并不清楚。

于 2013-07-04T14:25:52.037 回答
1

您可以使用 SingleThreadExecutor 在另一个Java 文档之后运行一个任务

因此它会将您的任务一个接一个地放置,它们将按顺序执行而不会阻塞主线程

于 2013-07-04T14:27:20.273 回答
1

试试这个,这将按预期工作。两个线程一个接一个地打印奇偶和主线程尽快退出。

public class YoThreD {

    static boolean isThread1 = false;

    public static synchronized boolean isThread1() {
        return isThread1 = !isThread1;
    }

    public static void main(String args[]) {

        Runnable runnableObject = new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    for (int i = 1; i <= 100; i++) {
                        try {
                            if (Thread.currentThread().getName().equals("thread1")) {
                                if (isThread1()){
                                    System.out.println(Thread.currentThread().getName() + "    :   " + i);
                                }else{
                                    this.notify();
                                    this.wait();
                                }
                            } else {
                                if (!isThread1()){
                                    System.out.println(Thread.currentThread().getName() + "    :   " + i);
                                    this.notify();
                                    this.wait();
                                }
                                else{
                                }
                            }
                        } catch (Exception e) {
                        }
                    }
                }
            }
        };
        Thread thread1 = new Thread(runnableObject);
        thread1.setName("thread1");
        thread1.start();
        Thread thread2 = new Thread(runnableObject);
        thread2.setName("thread2");
        thread2.start();
        System.out.println(Thread.currentThread().getName() + "Main thread finished");
    }
}
于 2018-07-09T21:47:57.057 回答
0

愚蠢的问题,但是如果线程 2 应该在线程 1 完成时执行……为什么不从线程 1 开始呢?

或者也许只是让线程 1 触发一个事件,而主线程可以启动新的事件来响应该事件。

我找到了这个例子,应该对你有用。

于 2013-07-04T14:26:18.957 回答
0

您可以使用以下几种方式一个接一个地运行两个线程:

  1. 通过使用 join() 方法。前任:

    Thread t1=new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 4; i++) {
                System.out.println("A " + i);
            }
        }
    });
    Thread t2=new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 4; i++) {
                System.out.println("B " + i);
            }
        }
    });
    
    1. 通过使用 wait() 和 notify() 方法:例如。

`

{
public class NotiffyAllExample {

    int flag = 1;

    public static void main(String[] args) {

        NotiffyAllExample notiffyAllExample = new NotiffyAllExample();

        A1 a = new A1(notiffyAllExample);
        B1 b = new B1(notiffyAllExample);
        C1 c = new C1(notiffyAllExample);
        a.start();
        b.start();
    }
}

class A1 extends Thread {

    NotiffyAllExample notiffyAllExample;

    public A1(net.citigroup.mexico.pg.test.test.NotiffyAllExample notiffyAllExample) {
        this.notiffyAllExample = notiffyAllExample;
    }

    @Override
    public void run() {

        try {
            synchronized (notiffyAllExample) {

                for (int i = 0; i < 4; i++) {

                    while (notiffyAllExample.flag != 1) {
                        notiffyAllExample.wait();
                    }
                    System.out.print("A ");
                }
                notiffyAllExample.flag = 2;
                notiffyAllExample.notifyAll();
            }
        } catch (Exception e) {
            System.out.println("Exception 1 :" + e.getMessage());
        }

    }
}

class B1 extends Thread {

    NotiffyAllExample notiffyAllExample;

    public B1(NotiffyAllExample notiffyAllExample) {
        this.notiffyAllExample = notiffyAllExample;
    }

    @Override
    public void run() {
        try {
            synchronized (notiffyAllExample) {

                for (int i = 0; i < 4; i++) {

                    while (notiffyAllExample.flag != 2) {
                        notiffyAllExample.wait();
                    }
                    System.out.print("B ");
                }
                notiffyAllExample.flag = 1;
                notiffyAllExample.notifyAll();

            }
        } catch (Exception e) {
            System.out.println("Exception 2 :" + e.getMessage());
        }

    }
}
}

`

于 2017-12-21T10:50:25.577 回答