【问题标题】:Execute two threads which wait one for the other while main thread continues执行两个线程,一个等待另一个,而主线程继续
【发布时间】:2013-07-04 14:15:20
【问题描述】:

如何启动两个线程,其中 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 才必须开始填充其链接表,否则数据库会给出完整性错误。 现在想象一下,由于复杂的链接表,我有几个具有不同优先级的线程,你有一个想法。

【问题讨论】:

  • 如果强制一个接一个地执行,为什么还需要 2 个线程?
  • 我在上面添加了“为什么我需要这个”.. 希望清楚
  • 我想我现在说得更清楚了 :)

标签: java multithreading executorservice


【解决方案1】:

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

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

【讨论】:

  • 上面的代码不起作用,main只有在first完成后才能继续运行。我认为 second 会锁定 main 直到 first 还没有完成。
【解决方案2】:

您可以使用CountDownLatch

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

【讨论】:

    【解决方案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();
    

    【讨论】:

    • 正是.. 我希望主线程继续执行而不是等待
    • 好的,它有效,撤销了减号。但我个人不会为了控制其他 2 个线程而创建第三个线程
    【解决方案4】:

    为什么不让线程 1 启动线程 2?

    // 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% 的后台工作相比,您为什么要这样做并不清楚。

    【讨论】:

    • 也许这个明显的解决方案太明显了——另一位发帖人提出了建议,但由于某种原因被否决了。这肯定是最简单的方法,比显式的信号建议要简单得多。
    【解决方案5】:

    您可以使用 SingleThreadExecutor 一个接一个地运行一个任务Java doc

    所以它会把你的任务一个接一个地放,它们会按顺序执行而不阻塞主线程

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

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

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

        我找到了this 的例子,应该适合你。

        【讨论】:

        • 这应该是评论,而不是答案。
        • 什么?这是实现 OP 似乎想要的完全合理的方式。
        【解决方案8】:

        您可以通过以下几种方式依次运行两个线程:

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

        `

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-21
          • 2015-02-22
          • 1970-01-01
          • 2021-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多