Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么';启动线程的不同方式有什么区别?_Java_Multithreading - Fatal编程技术网

Java 什么';启动线程的不同方式有什么区别?

Java 什么';启动线程的不同方式有什么区别?,java,multithreading,Java,Multithreading,我有一个名为MyThread的类,它扩展了Thread类并实现了run()函数。当我想运行它时,我有两种方法: 新建实例并调用函数,如:newmythread().start() 新建一个实例,将实例作为参数传递给线程的构造函数,然后调用线程的start函数。如下所示:(新线程(新MyThread)).start() 任何人都能分辨出两者的区别吗?因为你说过你的类扩展了线程,第二个有点多余。在您的第二个示例中,您并没有将类用作,而是将其用作 通常,您要么扩展线程,然后调用它自己的开始(您的#1)

我有一个名为
MyThread
的类,它扩展了Thread类并实现了
run()
函数。当我想运行它时,我有两种方法:

  • 新建实例并调用函数,如:
    newmythread().start()
  • 新建一个实例,将实例作为参数传递给线程的构造函数,然后调用线程的start函数。如下所示:
    (新线程(新MyThread)).start()

  • 任何人都能分辨出两者的区别吗?

    因为你说过你的类扩展了
    线程,第二个有点多余。在您的第二个示例中,您并没有将类用作,而是将其用作

    通常,您要么扩展
    线程
    ,然后调用它自己的
    开始
    (您的#1),要么实现
    可运行
    ,然后使用
    线程
    运行它(您的#2)。但是您不会扩展
    线程
    ,然后使用另一个
    线程
    来运行它

    就区别而言,如果您需要执行任何操作来控制或查询线程,那么在第一种情况下,您将在类的实例上使用
    thread
    方法;在第二种情况下,您将在使用
    newthread
    创建的实例上使用它们。如果扩展
    Thread
    ,但通过#2运行它,那么实例上的
    Thread
    方法是不相关的,可能会令人困惑

    最后一点通过示例可能更清楚:

    扩展
    线程
    的示例:

    class Foo extends Thread {
        public void run() {
            // ...
        }
    }
    
    // Create it
    Foo foo = new Foo();
    
    // Start it
    foo.start();
    
    // Wait for it to finish (for example)
    foo.join();
    
    注意,我们通过
    foo
    引用启动并连接了线程

    实现
    Runnable
    的示例:

    class Foo implements Runnable {
        public void run() {
            // ...
        }
    }
    
    // Create it
    Foo foo = new Foo();
    
    // Create a Thread to run it
    Thread thread = new Thread(foo);
    
    // Start it
    thread.start();
    
    // Wait for it to finish (for example)
    thread.join();
    
    注意:我们通过
    线程
    引用启动并连接线程

    不要这样做:

    …因为现在在
    foo
    Thread
    上都有
    Thread#join
    ;哪个是正确的?(答案是:
    thread
    上的一个,但是它很混乱,所以最好不要这样做。)

    您正在传递的
    MyThread
    实例只是充当
    Runnable
    而不是单独的线程

    这两种方式在逻辑上基本没有区别:

    Thread
    start()
    上执行的内部操作是调用
    Runnable的
    run()
    方法

       PThread pThread = new PThread(args);
       Thread t = new Thread(pThread);  
             // allowed as pThread is extending Thread and hence, 
             //an implementation of Runnable 
       t.start();
    
    当您执行
    新线程(new MyThread()).start()
    时,您只是多余的,因为
    线程本身实现了
    可运行


    但是,由于新线程将调用
    MyThread
    run()

    那么,您有两种方法来实现多线程

  • 扩展
    Thread
    并使用
    newmythreand().start()
    启动线程

  • 实现
    Runnable
    接口。在这种情况下,您可以使用
    (新线程(新MyThread)).start()
    ;开始一个线程

  • 有关详细信息,请参阅

    (新线程(新MyThread)).start()


    每个线程实现Runnable;在这种情况下,MyThread实例用作Runnable,新线程调用MyThread实现的run方法。您将无法使用MyThread停止线程(或通过任何方式控制它)。

    您不应该这样做。创建线程确实会更改一些变量,如
    ThreadGroup
    中的“未启动线程数”


    虽然它不应该引起问题,但它的风格不好,会让人困惑(“他为什么这么做?一定有很好的理由!”)。

    启动线程的方式(实现Runnable或扩展Thread类的类)

    这只是您应用的抽象,注意
    (Runnable对象更一般,因为Runnable对象可以为类而不是线程创建子类)
    良好的编码实践。

    In both of the cases Thread.start() will called
    

    如果您的类本身扩展了
    线程
    ,您可以按照第一种方法操作:

    MyThread myThread = new MyThread();
    myThread.start();
    
    如果查看,您将看到第二种方法针对的是(仅)实现
    Runnable
    (这意味着您的类只需要实现
    run()
    方法)的类


    区别在于
    Runnable
    只是一个接口,而
    Thread
    是一个类。这意味着,如果您希望将逻辑作为类的一部分,而该类出于某种原因需要扩展另一个类,那么您仍然可以实现
    可运行
    ,并使用第二种方法。

    线程本身就是
    可运行
    的实现。当创建并启动
    线程的实例时,它将执行自己的
    run()
    方法。如果将非null的
    Runnable target
    指定给它的构造函数,那么它将调用它的目标的
    run()
    方法,这从
    Thread
    类的实现的
    run()
    方法中可以明显看出:

    @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    
    创建新执行线程的两种方法:

  • 第一个是将类(即
    PThread
    )声明为
    Thread
    的子类:
    PThread扩展PThread
    ,并应重写
    class
    Thread的
    run
    方法。然后,我们可以轻松创建该类的实例化,并在其上调用
    start()

    PThread pThread = new PThread(args);
    pThread.start(); 
    
  • 第二个是声明一个实现
    Runnable
    接口的类:
    RThread实现Runnable
    ,然后实现
    run
    方法。我们必须实例化
    RThread
    并将其作为
    Runnable
    目标传递给
    Thread
    实例:

     RunThread rThread = new RunThread(args); // args constructor argument if required 
     Thread t = new Thread(rThread);
     t.start();
    
  • 从上面启动线程的方法可以看出,实际上允许将扩展
    线程的类(例如
    PThread
    )作为
    Runn传递给新的
    thread
    构造函数
     RunThread rThread = new RunThread(args); // args constructor argument if required 
     Thread t = new Thread(rThread);
     t.start();
    
       PThread pThread = new PThread(args);
       Thread t = new Thread(pThread);  
             // allowed as pThread is extending Thread and hence, 
             //an implementation of Runnable 
       t.start();