同步线程执行

时间:2013-06-12 17:58:40

标签: java multithreading

我的任务是按此顺序创建线程:如果A开始 - >开始B和C,如果B开始 - >开始D. 并以相反的顺序摧毁它们如果D然后B.如果B和C然后A.我希望你得到它。我设法做到了,但我想有更好的方法来做到这一点。你有什么建议吗?

在您发表评论之后,我已经更改了我的代码,而且更简单。但现在它看起来“愚蠢”。我想改变if语句和实现的核心,有什么建议吗? tnx的建议我正在和你学习。

这是我的新代码:

     import java.util.*;
class RobotController implements Runnable{
String name;

public void run() {
    Thread t = Thread.currentThread();
    System.out.println(t.getName() + " status = " + t.isAlive());
    System.out.println(t.getName() + " status = " + t.getState());

  }

public static void main(String args[]) throws InterruptedException{
    Thread thread_A = new Thread(new RobotController(), "Thread A");
    Thread thread_B = new Thread(new RobotController(), "Thread B");
    Thread thread_C = new Thread(new RobotController(), "Thread C");
    Thread thread_D = new Thread(new RobotController(), "Thread D");

    thread_A.start();
    thread_A.join();
    System.out.println(thread_A.getState());
    thread_B.start();
    thread_B.join();
    System.out.println(thread_B.getState());
    thread_C.start();
    thread_C.join();
    System.out.println(thread_C.getState());
    thread_D.start();
    System.out.println(thread_D.getState());


}

}

4 个答案:

答案 0 :(得分:3)

您的代码中存在一些缺陷,有时会导致其无法正常工作:

  1. 您致电thread_A.start(),然后选中了thread_A.isAlive()。现在,如果在检查thread_A.isAlive()条件之前已完成thread_A,那该怎么办?thread_Bthread_C永远不会启动。您的申请失败。
  2. 假设thread_A未完成且thread_A.isAlive()条件已通过,则thread_Bthread_C之前开始并不总是由Java线程调度程序保证。您的应用程序再次失败。
  3. 假设thread_Bthread_C之前开始,如果thread_B在检查thread_B.isAlive()之前完成,则if条件失败且thread_D永远不会开始。您的应用程序再次失败。
  4. 现在有一点需要思考:
    在调用join()方法后,无需检查线程是否处于活动状态。这是一个不必要的运行时开销。

    修改
    好的,这是代码的修改版本。我希望它能让你理解线程的动态:

    class RobotController implements Runnable
    {
        private final Object lock = new Object();
        private void notifyThread()
        {
            synchronized(lock)
            {
                lock.notify();
            }
        }
        public void run() 
        {
            synchronized(lock)
            {
                try
                {
                    System.out.println(Thread.currentThread().getName() + " started");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName()+ " stopped");
                }
                catch (InterruptedException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    
        public static void main(String args[]) throws InterruptedException
        {
            RobotController rca = new RobotController();
            RobotController rcb = new RobotController();
            RobotController rcc = new RobotController();
            RobotController rcd = new RobotController();
    
    
            Thread thread_A = new Thread(rca,"Thread A");
            Thread thread_B = new Thread(rcb,"Thread B");
            Thread thread_C = new Thread(rcc,"Thread C");
            Thread thread_D = new Thread(rcd,"Thread D");
    
            thread_A.start();
            while (thread_A.getState() != Thread.State.WAITING)
            {
                Thread.sleep(100);
            }
            thread_B.start();
            thread_C.start();
            while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING)
            {
                Thread.sleep(100);
            }
            thread_D.start();
            while (thread_D.getState() != Thread.State.WAITING)
            {
                Thread.sleep(100);
            }
            rcd.notifyThread();
            thread_D.join();
            rcc.notifyThread();
            thread_C.join();
            rcb.notifyThread();
            thread_B.join();
            rca.notifyThread();
        }
    
    }
    

    这是输出:

    Thread A started
    Thread B started
    Thread C started
    Thread D started
    Thread D stopped
    Thread C stopped
    Thread B stopped
    Thread A stopped
    

答案 1 :(得分:2)

在多线程中,除非公共数据由多个线程共享,否则不需要同步。 在您的情况下,您希望以特定顺序启动和停止线程。为此,Thread类中有join方法。 This链接显示了加入方法的好例子。

答案 2 :(得分:0)

在我看来,在run方法中使用synchronized (lock)来锁定对象是很奇怪的。原因是每个Thread对象都有不同的lock属性,属于每个对象。这意味着您正在尝试锁定不同的对象。实际上,它没有意义。

基本上,应该应用synchronized的对象是任何共享对象。例如,您需要计算一些内容,然后创建一个类对象以在类中共享它。在这种情况下,应该在读取或写入时锁定它。

答案 3 :(得分:0)

我想强调两点:

  1. 查看线程执行生命周期here。它说,当调用start()方法时,线程进入runnable状态而不是处于运行状态。当线程进入运行状态时,这意味着run()方法被执行。 CPU / OS决定应将哪个线程从runnable传输到正在运行的线程的优先级。例如。如果为4个线程调用start()方法,则它们不必按该特定顺序执行。 (多次在我的电脑上运行相同的程序会给我不同的输出。
  2. 在您的情况下,当执行条件if(thread_A.isAlive())时,线程A可能不处于运行状态。因此,如果哪个不正确,控制将不会进入。 为了纠正这种行为,在main中,应该实现一个while循环,它等待线程变为活动状态等等。

    2。在程序中,您尚未为线程指定名称,而是在run()方法中打印名称。在这种情况下,JVM按照执行的顺序将名称分配给线程,例如要执行的第一个线程的名称为“Thread-0”,依此类推。因此,我们将无法识别首先执行的线程。使用setName()方法分配名称。