当主线程继续时,执行两个线程,等待另一个线程

时间:2013-07-04 14:15:21

标签: java multithreading executorservice

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

我尝试过join()但是需要从必须等待另一个的线程调用它,没有办法像thread2.join(thread1)那样做; 如果我在main()中调用连接,那么我实际上会停止执行主线程而不仅仅是thread2。

因此我尝试使用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复制的表的链接表。 因此,thread2只有在thread1完成时才开始填充其链接表,否则数据库会给出完整性错误。 现在想象一下,由于复杂的链接表,我有几个不同优先级的线程,你有一个想法。

8 个答案:

答案 0 :(得分: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();

答案 1 :(得分:3)

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

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
    }
}

答案 2 :(得分:2)

您可以使用CountDownLatch

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

答案 3 :(得分: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%的后台工作,这一点都不清楚。

答案 4 :(得分:1)

您可以使用SingleThreadExecutor在另一个Java doc

之后运行一个任务

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

答案 5 :(得分: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");
    }
}

答案 6 :(得分:0)

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

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

我发现this示例,应该适合你。

答案 7 :(得分: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()方法:ex。
  2. `

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

    `